Fix merging enumerable content and validate content (#2531)

This commit is contained in:
James Newton-King
2021-05-15 13:45:00 +12:00
committed by GitHub
parent 2b0f7a2492
commit e44ab3348f
2 changed files with 88 additions and 14 deletions
@@ -46,6 +46,18 @@ namespace Newtonsoft.Json.Tests.Linq
[TestFixture]
public class MergeTests : TestFixtureBase
{
[Test]
public void MergeInvalidObject()
{
var a = new JObject();
ExceptionAssert.Throws<ArgumentException>(
() => 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()
{
+44 -14
View File
@@ -723,8 +723,14 @@ namespace Newtonsoft.Json.Linq
/// Merge the specified content into this <see cref="JToken"/>.
/// </summary>
/// <param name="content">The content to be merged.</param>
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
/// </summary>
/// <param name="content">The content to be merged.</param>
/// <param name="settings">The <see cref="JsonMergeSettings"/> used to merge the content.</param>
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<JToken> items = new HashSet<JToken>(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++;