diff --git a/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs b/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs
index add425d3..025110d2 100644
--- a/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs
@@ -569,5 +569,57 @@ namespace Newtonsoft.Json.Tests.Linq
Assert.AreEqual("name1", p.Name);
Assert.AreEqual(0, p.Count);
}
+
+ [Test]
+ public void MergeNullValue()
+ {
+ var source = new JObject
+ {
+ {"Property1", "value"},
+ {"Property2", new JObject()},
+ {"Property3", JValue.CreateNull()},
+ {"Property4", JValue.CreateUndefined()},
+ };
+
+ var patch = JObject.Parse("{Property1:null, Property2:null, Property3:null, Property4:null}");
+
+ source.Merge(patch, new JsonMergeSettings
+ {
+ MergetObjectHandling = MergeObjectHandling.Null,
+ });
+
+ Assert.IsNotNull(source["Property1"]);
+ Assert.AreEqual(JTokenType.Null, source["Property1"].Type);
+ Assert.IsNotNull(source["Property2"]);
+ Assert.AreEqual(JTokenType.Null, source["Property2"].Type);
+ Assert.IsNotNull(source["Property3"]);
+ Assert.AreEqual(JTokenType.Null, source["Property3"].Type);
+ Assert.IsNotNull(source["Property4"]);
+ Assert.AreEqual(JTokenType.Null, source["Property4"].Type);
+ }
+
+ [Test]
+ public void MergeUndefinedlValue()
+ {
+ var source = new JObject
+ {
+ {"Property1", "value"},
+ {"Property2", new JObject()},
+ {"Property3", JValue.CreateNull()},
+ {"Property4", JValue.CreateUndefined()},
+ };
+
+ var patch = JObject.Parse("{Property1:undefined, Property2:undefined, Property3:undefined, Property4:undefined}");
+
+ source.Merge(patch, new JsonMergeSettings
+ {
+ MergetObjectHandling = MergeObjectHandling.Undefined,
+ });
+
+ Assert.IsNull(source.Property("Property1"));
+ Assert.IsNull(source.Property("Property2"));
+ Assert.IsNull(source.Property("Property3"));
+ Assert.IsNull(source.Property("Property4"));
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs
index 0ef4b0ea..c9bfec54 100644
--- a/Src/Newtonsoft.Json/Linq/JObject.cs
+++ b/Src/Newtonsoft.Json/Linq/JObject.cs
@@ -171,11 +171,31 @@ namespace Newtonsoft.Json.Linq
}
else if (contentItem.Value != null)
{
+ if (settings != null)
+ {
+ if (contentItem.Value.Type == JTokenType.Null)
+ {
+ if ((settings.MergetObjectHandling & MergeObjectHandling.Null) != 0)
+ {
+ existingProperty.Value = contentItem.Value;
+ }
+ continue;
+ }
+
+ if (contentItem.Value.Type == JTokenType.Undefined)
+ {
+ if ((settings.MergetObjectHandling & MergeObjectHandling.Undefined) != 0)
+ {
+ existingProperty.Remove();
+ }
+ continue;
+ }
+ }
+
JContainer existingContainer = existingProperty.Value as JContainer;
if (existingContainer == null)
{
- if (contentItem.Value.Type != JTokenType.Null)
- existingProperty.Value = contentItem.Value;
+ existingProperty.Value = contentItem.Value;
}
else if (existingContainer.Type != contentItem.Value.Type)
{
diff --git a/Src/Newtonsoft.Json/Linq/JsonMergeSettings.cs b/Src/Newtonsoft.Json/Linq/JsonMergeSettings.cs
index 3f33c6a3..ac595c29 100644
--- a/Src/Newtonsoft.Json/Linq/JsonMergeSettings.cs
+++ b/Src/Newtonsoft.Json/Linq/JsonMergeSettings.cs
@@ -9,6 +9,8 @@ namespace Newtonsoft.Json.Linq
{
private MergeArrayHandling _mergeArrayHandling;
+ private MergeObjectHandling _mergeObjectHandling;
+
///
/// Gets or sets the method used when merging JSON arrays.
///
@@ -24,5 +26,21 @@ namespace Newtonsoft.Json.Linq
_mergeArrayHandling = value;
}
}
+
+ ///
+ /// Gets or sets the method used when merging JSON objects.
+ ///
+ /// The method used when merging JSON objects.
+ public MergeObjectHandling MergetObjectHandling
+ {
+ get { return _mergeObjectHandling; }
+ set
+ {
+ if ((value | MergeObjectHandling.All) != MergeObjectHandling.All)
+ throw new ArgumentOutOfRangeException("value");
+
+ _mergeObjectHandling = value;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Linq/MergeObjectHandling.cs b/Src/Newtonsoft.Json/Linq/MergeObjectHandling.cs
new file mode 100644
index 00000000..0a05165d
--- /dev/null
+++ b/Src/Newtonsoft.Json/Linq/MergeObjectHandling.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace Newtonsoft.Json.Linq
+{
+ ///
+ /// Specifies how JSON objects are merged together.
+ ///
+ [Flags]
+ public enum MergeObjectHandling
+ {
+ ///
+ /// Uses default behaviour (ignore null and undefined) to merge the objects.
+ ///
+ None = 0,
+
+ ///
+ /// The target object's null value will be set to the source object.
+ ///
+ Null = 1,
+
+ ///
+ /// The target objects's explicit undefined value will remove the source object's property.
+ ///
+ Undefined = 2,
+
+ ///
+ /// Merge objects uses and policy.
+ ///
+ All = Null | Undefined,
+ }
+}
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
index 63db3c2d..6921bc6d 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
@@ -136,6 +136,7 @@
+