-Added Merge to LINQ to JSON
This commit is contained in:
@@ -120,6 +120,25 @@ namespace Newtonsoft.Json.Tests.Converters
|
||||
return node;
|
||||
}
|
||||
|
||||
#if !NET20
|
||||
public class Foo
|
||||
{
|
||||
public XElement Bar { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeAndDeserializeXElement()
|
||||
{
|
||||
Foo foo = new Foo { Bar = null };
|
||||
string json = JsonConvert.SerializeObject(foo);
|
||||
|
||||
Assert.AreEqual(@"{""Bar"":null}", json);
|
||||
Foo foo2 = JsonConvert.DeserializeObject<Foo>(json);
|
||||
|
||||
Assert.IsNull(foo2.Bar);
|
||||
}
|
||||
#endif
|
||||
|
||||
[Test]
|
||||
public void SerializeXmlElement()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,538 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.Linq
|
||||
{
|
||||
[TestFixture]
|
||||
public class MergeTests : TestFixtureBase
|
||||
{
|
||||
[Test]
|
||||
public void MergeObjectProperty()
|
||||
{
|
||||
var left = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Property1 = 1
|
||||
});
|
||||
var right = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Property2 = 2
|
||||
});
|
||||
|
||||
left.Merge(right);
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Property1"": 1,
|
||||
""Property2"": 2
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeChildObject()
|
||||
{
|
||||
var left = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Property1 = new { SubProperty1 = 1 }
|
||||
});
|
||||
var right = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Property1 = new { SubProperty2 = 2 }
|
||||
});
|
||||
|
||||
left.Merge(right);
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Property1"": {
|
||||
""SubProperty1"": 1,
|
||||
""SubProperty2"": 2
|
||||
}
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeMismatchedTypesRoot()
|
||||
{
|
||||
var left = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Property1 = new { SubProperty1 = 1 }
|
||||
});
|
||||
var right = (JArray)JToken.FromObject(new object[]
|
||||
{
|
||||
new { Property1 = 1 },
|
||||
new { Property1 = 1 }
|
||||
});
|
||||
|
||||
left.Merge(right);
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Property1"": {
|
||||
""SubProperty1"": 1
|
||||
}
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeMultipleObjects()
|
||||
{
|
||||
var left = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Property1 = new { SubProperty1 = 1 }
|
||||
});
|
||||
var right = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Property1 = new { SubProperty2 = 2 },
|
||||
Property2 = 2
|
||||
});
|
||||
|
||||
left.Merge(right);
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Property1"": {
|
||||
""SubProperty1"": 1,
|
||||
""SubProperty2"": 2
|
||||
},
|
||||
""Property2"": 2
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeArray()
|
||||
{
|
||||
var left = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Array1 = new object[]
|
||||
{
|
||||
new
|
||||
{
|
||||
Property1 = new
|
||||
{
|
||||
Property1 = 1,
|
||||
Property2 = 2,
|
||||
Property3 = 3,
|
||||
Property4 = 4,
|
||||
Property5 = (object)null
|
||||
}
|
||||
},
|
||||
new { },
|
||||
3,
|
||||
null,
|
||||
5,
|
||||
null
|
||||
}
|
||||
});
|
||||
var right = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Array1 = new object[]
|
||||
{
|
||||
new
|
||||
{
|
||||
Property1 = new
|
||||
{
|
||||
Property1 = (object)null,
|
||||
Property2 = 3,
|
||||
Property3 = new
|
||||
{
|
||||
|
||||
},
|
||||
Property5 = (object)null
|
||||
}
|
||||
},
|
||||
null,
|
||||
null,
|
||||
4,
|
||||
5.1,
|
||||
null,
|
||||
new
|
||||
{
|
||||
Property1 = 1
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
left.Merge(right, new JsonMergeSettings
|
||||
{
|
||||
MergeArrayHandling = MergeArrayHandling.Merge
|
||||
});
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Array1"": [
|
||||
{
|
||||
""Property1"": {
|
||||
""Property1"": 1,
|
||||
""Property2"": 3,
|
||||
""Property3"": {},
|
||||
""Property4"": 4,
|
||||
""Property5"": null
|
||||
}
|
||||
},
|
||||
{},
|
||||
3,
|
||||
4,
|
||||
5.1,
|
||||
null,
|
||||
{
|
||||
""Property1"": 1
|
||||
}
|
||||
]
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConcatArray()
|
||||
{
|
||||
var left = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Array1 = new object[]
|
||||
{
|
||||
new { Property1 = 1 },
|
||||
new { Property1 = 1 }
|
||||
}
|
||||
});
|
||||
var right = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Array1 = new object[]
|
||||
{
|
||||
new { Property1 = 1 },
|
||||
new { Property2 = 2 },
|
||||
new { Property3 = 3 }
|
||||
}
|
||||
});
|
||||
|
||||
left.Merge(right, new JsonMergeSettings
|
||||
{
|
||||
MergeArrayHandling = MergeArrayHandling.Concat
|
||||
});
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Array1"": [
|
||||
{
|
||||
""Property1"": 1
|
||||
},
|
||||
{
|
||||
""Property1"": 1
|
||||
},
|
||||
{
|
||||
""Property1"": 1
|
||||
},
|
||||
{
|
||||
""Property2"": 2
|
||||
},
|
||||
{
|
||||
""Property3"": 3
|
||||
}
|
||||
]
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeMismatchingTypesInArray()
|
||||
{
|
||||
var left = (JArray)JToken.FromObject(new object[]
|
||||
{
|
||||
true,
|
||||
null,
|
||||
new { Property1 = 1 },
|
||||
new object[] { 1 },
|
||||
new { Property1 = 1 },
|
||||
1,
|
||||
new object[] { 1 }
|
||||
});
|
||||
var right = (JArray)JToken.FromObject(new object[]
|
||||
{
|
||||
1,
|
||||
5,
|
||||
new object[] { 1 },
|
||||
new { Property1 = 1 },
|
||||
true,
|
||||
new { Property1 = 1 },
|
||||
null
|
||||
});
|
||||
|
||||
left.Merge(right, new JsonMergeSettings
|
||||
{
|
||||
MergeArrayHandling = MergeArrayHandling.Merge
|
||||
});
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"[
|
||||
1,
|
||||
5,
|
||||
{
|
||||
""Property1"": 1
|
||||
},
|
||||
[
|
||||
1
|
||||
],
|
||||
{
|
||||
""Property1"": 1
|
||||
},
|
||||
{
|
||||
""Property1"": 1
|
||||
},
|
||||
[
|
||||
1
|
||||
]
|
||||
]", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeMismatchingTypesInObject()
|
||||
{
|
||||
var left = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Property1 = new object[]
|
||||
{
|
||||
1
|
||||
},
|
||||
Property2 = new object[]
|
||||
{
|
||||
1
|
||||
},
|
||||
Property3 = true,
|
||||
Property4 = true
|
||||
});
|
||||
var right = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Property1 = new { Nested = true },
|
||||
Property2 = true,
|
||||
Property3 = new object[]
|
||||
{
|
||||
1
|
||||
},
|
||||
Property4 = (object)null
|
||||
});
|
||||
|
||||
left.Merge(right);
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Property1"": {
|
||||
""Nested"": true
|
||||
},
|
||||
""Property2"": true,
|
||||
""Property3"": [
|
||||
1
|
||||
],
|
||||
""Property4"": true
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeArrayOverwrite_Nested()
|
||||
{
|
||||
var left = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Array1 = new object[]
|
||||
{
|
||||
1,
|
||||
2,
|
||||
3
|
||||
}
|
||||
});
|
||||
var right = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Array1 = new object[]
|
||||
{
|
||||
4,
|
||||
5
|
||||
}
|
||||
});
|
||||
|
||||
left.Merge(right, new JsonMergeSettings
|
||||
{
|
||||
MergeArrayHandling = MergeArrayHandling.Replace
|
||||
});
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Array1"": [
|
||||
4,
|
||||
5
|
||||
]
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeArrayOverwrite_Root()
|
||||
{
|
||||
var left = (JArray)JToken.FromObject(new object[]
|
||||
{
|
||||
1,
|
||||
2,
|
||||
3
|
||||
});
|
||||
var right = (JArray)JToken.FromObject(new object[]
|
||||
{
|
||||
4,
|
||||
5
|
||||
});
|
||||
|
||||
left.Merge(right, new JsonMergeSettings
|
||||
{
|
||||
MergeArrayHandling = MergeArrayHandling.Replace
|
||||
});
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"[
|
||||
4,
|
||||
5
|
||||
]", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnionArrays()
|
||||
{
|
||||
var left = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Array1 = new object[]
|
||||
{
|
||||
new { Property1 = 1 },
|
||||
new { Property1 = 1 }
|
||||
}
|
||||
});
|
||||
var right = (JObject)JToken.FromObject(new
|
||||
{
|
||||
Array1 = new object[]
|
||||
{
|
||||
new { Property1 = 1 },
|
||||
new { Property2 = 2 },
|
||||
new { Property3 = 3 }
|
||||
}
|
||||
});
|
||||
|
||||
left.Merge(right, new JsonMergeSettings
|
||||
{
|
||||
MergeArrayHandling = MergeArrayHandling.Union
|
||||
});
|
||||
|
||||
string json = left.ToString();
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Array1"": [
|
||||
{
|
||||
""Property1"": 1
|
||||
},
|
||||
{
|
||||
""Property1"": 1
|
||||
},
|
||||
{
|
||||
""Property2"": 2
|
||||
},
|
||||
{
|
||||
""Property3"": 3
|
||||
}
|
||||
]
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeJProperty()
|
||||
{
|
||||
JProperty p1 = new JProperty("p1", 1);
|
||||
JProperty p2 = new JProperty("p2", 2);
|
||||
|
||||
p1.Merge(p2);
|
||||
Assert.AreEqual(2, (int)p1.Value);
|
||||
|
||||
JProperty p3 = new JProperty("p3");
|
||||
|
||||
p1.Merge(p3);
|
||||
Assert.AreEqual(2, (int)p1.Value);
|
||||
|
||||
JProperty p4 = new JProperty("p4", null);
|
||||
|
||||
p1.Merge(p4);
|
||||
Assert.AreEqual(2, (int)p1.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeJConstructor()
|
||||
{
|
||||
JConstructor c1 = new JConstructor("c1", new[] { 1, 2 });
|
||||
JConstructor c2 = new JConstructor("c2", new[] { 3, 4 });
|
||||
|
||||
c1.Merge(c2);
|
||||
Assert.AreEqual("c2", c1.Name);
|
||||
CollectionAssert.AreEquivalent(new[] { 1, 2, 3, 4 }, c1.Select(i => (int)i));
|
||||
|
||||
JConstructor c3 = new JConstructor();
|
||||
c1.Merge(c3);
|
||||
Assert.AreEqual("c2", c1.Name);
|
||||
|
||||
JConstructor c4 = new JConstructor("c4", new[] { 5, 6 });
|
||||
c1.Merge(c4, new JsonMergeSettings
|
||||
{
|
||||
MergeArrayHandling = MergeArrayHandling.Replace
|
||||
});
|
||||
Assert.AreEqual("c4", c1.Name);
|
||||
CollectionAssert.AreEquivalent(new[] { 5, 6 }, c1.Select(i => (int)i));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeDefaultContainers()
|
||||
{
|
||||
JConstructor c = new JConstructor();
|
||||
c.Merge(new JConstructor());
|
||||
Assert.AreEqual(null, c.Name);
|
||||
Assert.AreEqual(0, c.Count);
|
||||
|
||||
JObject o = new JObject();
|
||||
o.Merge(new JObject());
|
||||
Assert.AreEqual(0, o.Count);
|
||||
|
||||
JArray a = new JArray();
|
||||
a.Merge(new JArray());
|
||||
Assert.AreEqual(0, a.Count);
|
||||
|
||||
JProperty p = new JProperty("name1");
|
||||
p.Merge(new JProperty("name2"));
|
||||
Assert.AreEqual("name1", p.Name);
|
||||
Assert.AreEqual(0, p.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergeNull()
|
||||
{
|
||||
JConstructor c = new JConstructor();
|
||||
c.Merge(null);
|
||||
Assert.AreEqual(null, c.Name);
|
||||
Assert.AreEqual(0, c.Count);
|
||||
|
||||
JObject o = new JObject();
|
||||
o.Merge(null);
|
||||
Assert.AreEqual(0, o.Count);
|
||||
|
||||
JArray a = new JArray();
|
||||
a.Merge(null);
|
||||
Assert.AreEqual(0, a.Count);
|
||||
|
||||
JProperty p = new JProperty("name1");
|
||||
p.Merge(null);
|
||||
Assert.AreEqual("name1", p.Name);
|
||||
Assert.AreEqual(0, p.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,6 +136,7 @@
|
||||
<Compile Include="Linq\JsonPath\JPathExecuteTests.cs" />
|
||||
<Compile Include="Linq\JsonPath\JPathParseTests.cs" />
|
||||
<Compile Include="Linq\JsonPath\QueryExpressionTests.cs" />
|
||||
<Compile Include="Linq\MergeTests.cs" />
|
||||
<Compile Include="Serialization\ConstructorHandlingTests.cs" />
|
||||
<Compile Include="Serialization\ContractResolverTests.cs" />
|
||||
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
|
||||
|
||||
@@ -257,6 +257,7 @@
|
||||
<Compile Include="Linq\JsonPath\JPathExecuteTests.cs" />
|
||||
<Compile Include="Linq\JsonPath\JPathParseTests.cs" />
|
||||
<Compile Include="Linq\JsonPath\QueryExpressionTests.cs" />
|
||||
<Compile Include="Linq\MergeTests.cs" />
|
||||
<Compile Include="Schema\JsonSchemaSpecTests.cs" />
|
||||
<Compile Include="Serialization\ConstructorHandlingTests.cs" />
|
||||
<Compile Include="Serialization\ContractResolverTests.cs" />
|
||||
|
||||
@@ -141,6 +141,7 @@
|
||||
<Compile Include="Linq\JsonPath\JPathExecuteTests.cs" />
|
||||
<Compile Include="Linq\JsonPath\JPathParseTests.cs" />
|
||||
<Compile Include="Linq\JsonPath\QueryExpressionTests.cs" />
|
||||
<Compile Include="Linq\MergeTests.cs" />
|
||||
<Compile Include="Serialization\ConstructorHandlingTests.cs" />
|
||||
<Compile Include="Serialization\ContractResolverTests.cs" />
|
||||
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
|
||||
|
||||
@@ -138,6 +138,7 @@
|
||||
<Compile Include="Linq\JsonPath\JPathExecuteTests.cs" />
|
||||
<Compile Include="Linq\JsonPath\JPathParseTests.cs" />
|
||||
<Compile Include="Linq\JsonPath\QueryExpressionTests.cs" />
|
||||
<Compile Include="Linq\MergeTests.cs" />
|
||||
<Compile Include="Serialization\ConstructorHandlingTests.cs" />
|
||||
<Compile Include="Serialization\ContractResolverTests.cs" />
|
||||
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
|
||||
|
||||
@@ -227,6 +227,7 @@
|
||||
<Compile Include="Linq\JTokenWriterTest.cs" />
|
||||
<Compile Include="Linq\JValueTests.cs" />
|
||||
<Compile Include="Linq\LinqToJsonTest.cs" />
|
||||
<Compile Include="Linq\MergeTests.cs" />
|
||||
<Compile Include="PerformanceTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Schema\ExtensionsTests.cs" />
|
||||
|
||||
@@ -75,4 +75,4 @@ using System.Security;
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("6.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("6.0.3.17521")]
|
||||
[assembly: AssemblyFileVersion("6.0.4.17601")]
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.IO;
|
||||
@@ -233,6 +234,17 @@ namespace Newtonsoft.Json.Linq
|
||||
set { SetItem(index, value); }
|
||||
}
|
||||
|
||||
internal override void MergeItem(object content, JsonMergeSettings settings)
|
||||
{
|
||||
IEnumerable a = (IsMultiContent(content) || content is JArray)
|
||||
? (IEnumerable)content
|
||||
: null;
|
||||
if (a == null)
|
||||
return;
|
||||
|
||||
MergeEnumerableContent(this, a, settings);
|
||||
}
|
||||
|
||||
#region IList<JToken> Members
|
||||
/// <summary>
|
||||
/// Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1"/>.
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.Globalization;
|
||||
@@ -47,6 +48,17 @@ namespace Newtonsoft.Json.Linq
|
||||
get { return _values; }
|
||||
}
|
||||
|
||||
internal override void MergeItem(object content, JsonMergeSettings settings)
|
||||
{
|
||||
JConstructor c = content as JConstructor;
|
||||
if (c == null)
|
||||
return;
|
||||
|
||||
if (c.Name != null)
|
||||
Name = c.Name;
|
||||
MergeEnumerableContent(this, c, settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this constructor.
|
||||
/// </summary>
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Newtonsoft.Json.Linq
|
||||
#if !(NETFX_CORE || PORTABLE || PORTABLE40)
|
||||
, ITypedList, IBindingList
|
||||
#elif PORTABLE
|
||||
, INotifyCollectionChanged
|
||||
, INotifyCollectionChanged
|
||||
#endif
|
||||
, IList
|
||||
#if !(NET20 || NET35 || NETFX_CORE || PORTABLE40 || PORTABLE)
|
||||
@@ -588,7 +588,7 @@ namespace Newtonsoft.Json.Linq
|
||||
}
|
||||
}
|
||||
|
||||
internal JToken CreateFromContent(object content)
|
||||
internal static JToken CreateFromContent(object content)
|
||||
{
|
||||
if (content is JToken)
|
||||
return (JToken)content;
|
||||
@@ -623,6 +623,27 @@ namespace Newtonsoft.Json.Linq
|
||||
ClearItems();
|
||||
}
|
||||
|
||||
internal abstract void MergeItem(object content, JsonMergeSettings settings);
|
||||
|
||||
/// <summary>
|
||||
/// Merge the specified content into this <see cref="JToken"/>.
|
||||
/// </summary>
|
||||
/// <param name="content">The content to be merged.</param>
|
||||
public void Merge(object content)
|
||||
{
|
||||
MergeItem(content, new JsonMergeSettings());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merge the specified content into this <see cref="JToken"/> using <see cref="JsonMergeSettings"/>.
|
||||
/// </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)
|
||||
{
|
||||
MergeItem(content, settings);
|
||||
}
|
||||
|
||||
internal void ReadTokenFrom(JsonReader reader)
|
||||
{
|
||||
int startDepth = reader.Depth;
|
||||
@@ -1007,5 +1028,86 @@ namespace Newtonsoft.Json.Linq
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
internal static void MergeEnumerableContent(JContainer target, IEnumerable content, JsonMergeSettings settings)
|
||||
{
|
||||
switch (settings.MergeArrayHandling)
|
||||
{
|
||||
case MergeArrayHandling.Concat:
|
||||
foreach (JToken item in content)
|
||||
{
|
||||
target.Add(item);
|
||||
}
|
||||
break;
|
||||
case MergeArrayHandling.Union:
|
||||
#if !NET20
|
||||
HashSet<JToken> items = new HashSet<JToken>(target, EqualityComparer);
|
||||
|
||||
foreach (JToken item in content)
|
||||
{
|
||||
if (items.Add(item))
|
||||
{
|
||||
target.Add(item);
|
||||
}
|
||||
}
|
||||
#else
|
||||
IDictionary<JToken, bool> items = new Dictionary<JToken, bool>(EqualityComparer);
|
||||
foreach (JToken t in target)
|
||||
{
|
||||
items[t] = true;
|
||||
}
|
||||
|
||||
foreach (JToken item in content)
|
||||
{
|
||||
if (!items.ContainsKey(item))
|
||||
{
|
||||
items[item] = true;
|
||||
target.Add(item);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case MergeArrayHandling.Replace:
|
||||
target.ClearItems();
|
||||
foreach (JToken item in content)
|
||||
{
|
||||
target.Add(item);
|
||||
}
|
||||
break;
|
||||
case MergeArrayHandling.Merge:
|
||||
int i = 0;
|
||||
foreach (object targetItem in content)
|
||||
{
|
||||
if (i < target.Count)
|
||||
{
|
||||
JToken sourceItem = target[i];
|
||||
|
||||
JContainer existingContainer = sourceItem as JContainer;
|
||||
if (existingContainer != null)
|
||||
{
|
||||
existingContainer.Merge(targetItem, settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (targetItem != null)
|
||||
{
|
||||
JToken contentValue = CreateFromContent(targetItem);
|
||||
if (contentValue.Type != JTokenType.Null)
|
||||
target[i] = contentValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target.Add(targetItem);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("settings", "Unexpected merge array handling when merging JSON.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,6 +155,40 @@ namespace Newtonsoft.Json.Linq
|
||||
throw new ArgumentException("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, newProperty.Name, GetType()));
|
||||
}
|
||||
|
||||
internal override void MergeItem(object content, JsonMergeSettings settings)
|
||||
{
|
||||
JObject o = content as JObject;
|
||||
if (o == null)
|
||||
return;
|
||||
|
||||
foreach (KeyValuePair<string, JToken> contentItem in o)
|
||||
{
|
||||
JProperty existingProperty = Property(contentItem.Key);
|
||||
|
||||
if (existingProperty == null)
|
||||
{
|
||||
Add(contentItem.Key, contentItem.Value);
|
||||
}
|
||||
else if (contentItem.Value != null)
|
||||
{
|
||||
JContainer existingContainer = existingProperty.Value as JContainer;
|
||||
if (existingContainer == null)
|
||||
{
|
||||
if (contentItem.Value.Type != JTokenType.Null)
|
||||
existingProperty.Value = contentItem.Value;
|
||||
}
|
||||
else if (existingContainer.Type != contentItem.Value.Type)
|
||||
{
|
||||
existingProperty.Value = contentItem.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
existingContainer.Merge(contentItem.Value, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void InternalPropertyChanged(JProperty childProperty)
|
||||
{
|
||||
OnPropertyChanged(childProperty.Name);
|
||||
|
||||
@@ -145,6 +145,16 @@ namespace Newtonsoft.Json.Linq
|
||||
return (Value == item);
|
||||
}
|
||||
|
||||
internal override void MergeItem(object content, JsonMergeSettings settings)
|
||||
{
|
||||
JProperty p = content as JProperty;
|
||||
if (p == null)
|
||||
return;
|
||||
|
||||
if (p.Value != null && p.Value.Type != JTokenType.Null)
|
||||
Value = p.Value;
|
||||
}
|
||||
|
||||
internal override void ClearItems()
|
||||
{
|
||||
throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace Newtonsoft.Json.Linq
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the settings used when merging JSON.
|
||||
/// </summary>
|
||||
public class JsonMergeSettings
|
||||
{
|
||||
private MergeArrayHandling _mergeArrayHandling;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the method used when merging JSON arrays.
|
||||
/// </summary>
|
||||
/// <value>The method used when merging JSON arrays.</value>
|
||||
public MergeArrayHandling MergeArrayHandling
|
||||
{
|
||||
get { return _mergeArrayHandling; }
|
||||
set
|
||||
{
|
||||
if (value < MergeArrayHandling.Concat || value > MergeArrayHandling.Merge)
|
||||
throw new ArgumentOutOfRangeException("value");
|
||||
|
||||
_mergeArrayHandling = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Newtonsoft.Json.Linq
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies how JSON arrays are merged together.
|
||||
/// </summary>
|
||||
public enum MergeArrayHandling
|
||||
{
|
||||
/// <summary>Concatenate arrays.</summary>
|
||||
Concat,
|
||||
|
||||
/// <summary>Union arrays, skipping items that already exist.</summary>
|
||||
Union,
|
||||
|
||||
/// <summary>Replace all array items.</summary>
|
||||
Replace,
|
||||
|
||||
/// <summary>Merge array items together, matched by index.</summary>
|
||||
Merge
|
||||
}
|
||||
}
|
||||
@@ -107,6 +107,7 @@
|
||||
<Compile Include="JsonExtensionDataAttribute.cs" />
|
||||
<Compile Include="JsonPosition.cs" />
|
||||
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
|
||||
<Compile Include="Linq\JsonMergeSettings.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
|
||||
@@ -117,6 +118,7 @@
|
||||
<Compile Include="Linq\JsonPath\QueryExpression.cs" />
|
||||
<Compile Include="Linq\JsonPath\QueryFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ScanFilter.cs" />
|
||||
<Compile Include="Linq\MergeArrayHandling.cs" />
|
||||
<Compile Include="MetadataPropertyHandling.cs" />
|
||||
<Compile Include="SerializationBinder.cs" />
|
||||
<Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
<Compile Include="JsonPosition.cs" />
|
||||
<Compile Include="Linq\JPropertyDescriptor.cs" />
|
||||
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
|
||||
<Compile Include="Linq\JsonMergeSettings.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
|
||||
@@ -129,6 +130,7 @@
|
||||
<Compile Include="Linq\JsonPath\QueryExpression.cs" />
|
||||
<Compile Include="Linq\JsonPath\QueryFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ScanFilter.cs" />
|
||||
<Compile Include="Linq\MergeArrayHandling.cs" />
|
||||
<Compile Include="MetadataPropertyHandling.cs" />
|
||||
<Compile Include="SerializationBinder.cs" />
|
||||
<Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
|
||||
|
||||
@@ -120,6 +120,7 @@
|
||||
<Compile Include="JsonExtensionDataAttribute.cs" />
|
||||
<Compile Include="JsonPosition.cs" />
|
||||
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
|
||||
<Compile Include="Linq\JsonMergeSettings.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
|
||||
@@ -130,6 +131,7 @@
|
||||
<Compile Include="Linq\JsonPath\QueryExpression.cs" />
|
||||
<Compile Include="Linq\JsonPath\QueryFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ScanFilter.cs" />
|
||||
<Compile Include="Linq\MergeArrayHandling.cs" />
|
||||
<Compile Include="MetadataPropertyHandling.cs" />
|
||||
<Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
|
||||
<Compile Include="Serialization\ExpressionValueProvider.cs" />
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
<Compile Include="Linq\JPropertyDescriptor.cs" />
|
||||
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
|
||||
<Compile Include="Linq\JRaw.cs" />
|
||||
<Compile Include="Linq\JsonMergeSettings.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
|
||||
@@ -128,6 +129,7 @@
|
||||
<Compile Include="Linq\JTokenType.cs" />
|
||||
<Compile Include="Linq\JTokenWriter.cs" />
|
||||
<Compile Include="Linq\JValue.cs" />
|
||||
<Compile Include="Linq\MergeArrayHandling.cs" />
|
||||
<Compile Include="MemberSerialization.cs" />
|
||||
<Compile Include="MetadataPropertyHandling.cs" />
|
||||
<Compile Include="MissingMemberHandling.cs" />
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
<Compile Include="Linq\JPropertyDescriptor.cs" />
|
||||
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
|
||||
<Compile Include="Linq\JRaw.cs" />
|
||||
<Compile Include="Linq\JsonMergeSettings.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
|
||||
@@ -133,6 +134,7 @@
|
||||
<Compile Include="Linq\JTokenType.cs" />
|
||||
<Compile Include="Linq\JTokenWriter.cs" />
|
||||
<Compile Include="Linq\JValue.cs" />
|
||||
<Compile Include="Linq\MergeArrayHandling.cs" />
|
||||
<Compile Include="MemberSerialization.cs" />
|
||||
<Compile Include="MetadataPropertyHandling.cs" />
|
||||
<Compile Include="MissingMemberHandling.cs" />
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
<Compile Include="Linq\JContainer.cs" />
|
||||
<Compile Include="Linq\JEnumerable.cs" />
|
||||
<Compile Include="Linq\JObject.cs" />
|
||||
<Compile Include="Linq\JsonMergeSettings.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
|
||||
<Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
|
||||
@@ -132,6 +133,7 @@
|
||||
<Compile Include="Linq\JTokenType.cs" />
|
||||
<Compile Include="Linq\JTokenWriter.cs" />
|
||||
<Compile Include="Linq\JValue.cs" />
|
||||
<Compile Include="Linq\MergeArrayHandling.cs" />
|
||||
<Compile Include="MemberSerialization.cs" />
|
||||
<Compile Include="MetadataPropertyHandling.cs" />
|
||||
<Compile Include="MissingMemberHandling.cs" />
|
||||
|
||||
@@ -91,5 +91,5 @@ using System.Security;
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("6.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("6.0.3.17521")]
|
||||
[assembly: AssemblyFileVersion("6.0.4.17601")]
|
||||
[assembly: CLSCompliant(true)]
|
||||
|
||||
Reference in New Issue
Block a user