diff --git a/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs b/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs index 7108c92e..db660052 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs @@ -46,6 +46,18 @@ namespace Newtonsoft.Json.Tests.Linq [TestFixture] public class MergeTests : TestFixtureBase { + [Test] + public void MergeInvalidObject() + { + var a = new JObject(); + + ExceptionAssert.Throws( + () => a.Merge(new Version()), + @"Could not determine JSON object type for type System.Version. +Parameter name: content", + @"Could not determine JSON object type for type System.Version. (Parameter 'content')"); + } + [Test] public void MergeArraySelf() { @@ -70,6 +82,38 @@ namespace Newtonsoft.Json.Tests.Linq }, a); } + [Test] + public void MergeArrayIntoArray_Replace() + { + var a = new JArray { "1", "2" }; + a.Merge(new string[] { "3", "4" }, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Replace }); + Assert.AreEqual(new JArray { "3", "4" }, a); + } + + [Test] + public void MergeArrayIntoArray_Concat() + { + var a = new JArray { "1", "2" }; + a.Merge(new string[] { "3", "4" }, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Concat }); + Assert.AreEqual(new JArray { "1", "2", "3", "4" }, a); + } + + [Test] + public void MergeArrayIntoArray_Union() + { + var a = new JArray { "1", "2" }; + a.Merge(new string[] { "2", "3", "4" }, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Union }); + Assert.AreEqual(new JArray { "1", "2", "3", "4" }, a); + } + + [Test] + public void MergeArrayIntoArray_Merge() + { + var a = new JArray { "1", "2" }; + a.Merge(new string[] { "2" }, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); + Assert.AreEqual(new JArray { "2", "2" }, a); + } + [Test] public void MergeNullString() { diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs index 945de5c7..07f833bd 100644 --- a/Src/Newtonsoft.Json/Linq/JContainer.cs +++ b/Src/Newtonsoft.Json/Linq/JContainer.cs @@ -723,8 +723,14 @@ namespace Newtonsoft.Json.Linq /// Merge the specified content into this . /// /// The content to be merged. - public void Merge(object content) + public void Merge(object? content) { + if (content == null) + { + return; + } + + ValidateContent(content); MergeItem(content, null); } @@ -733,11 +739,31 @@ namespace Newtonsoft.Json.Linq /// /// The content to be merged. /// The used to merge the content. - public void Merge(object content, JsonMergeSettings? settings) + public void Merge(object? content, JsonMergeSettings? settings) { + if (content == null) + { + return; + } + + ValidateContent(content); MergeItem(content, settings); } + private void ValidateContent(object content) + { + if (content.GetType().IsSubclassOf(typeof(JToken))) + { + return; + } + if (IsMultiContent(content)) + { + return; + } + + throw new ArgumentException("Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, content.GetType()), nameof(content)); + } + internal void ReadTokenFrom(JsonReader reader, JsonLoadSettings? options) { int startDepth = reader.Depth; @@ -1141,20 +1167,22 @@ namespace Newtonsoft.Json.Linq switch (settings?.MergeArrayHandling ?? MergeArrayHandling.Concat) { case MergeArrayHandling.Concat: - foreach (JToken item in content) + foreach (object item in content) { - target.Add(item); + target.Add(CreateFromContent(item)); } break; case MergeArrayHandling.Union: #if HAVE_HASH_SET HashSet items = new HashSet(target, EqualityComparer); - foreach (JToken item in content) + foreach (object item in content) { - if (items.Add(item)) + JToken contentItem = CreateFromContent(item); + + if (items.Add(contentItem)) { - target.Add(item); + target.Add(contentItem); } } #else @@ -1164,12 +1192,14 @@ namespace Newtonsoft.Json.Linq items[t] = true; } - foreach (JToken item in content) + foreach (object item in content) { - if (!items.ContainsKey(item)) + JToken contentItem = CreateFromContent(item); + + if (!items.ContainsKey(contentItem)) { - items[item] = true; - target.Add(item); + items[contentItem] = true; + target.Add(contentItem); } } #endif @@ -1180,9 +1210,9 @@ namespace Newtonsoft.Json.Linq break; } target.ClearItems(); - foreach (JToken item in content) + foreach (object item in content) { - target.Add(item); + target.Add(CreateFromContent(item)); } break; case MergeArrayHandling.Merge: @@ -1211,7 +1241,7 @@ namespace Newtonsoft.Json.Linq } else { - target.Add(targetItem); + target.Add(CreateFromContent(targetItem)); } i++;