From 5fc738247f85fc486d9d36c69ebc376da01e8a0c Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Fri, 1 Aug 2014 21:27:38 +1200 Subject: [PATCH] -Added Merge to LINQ to JSON --- .../Converters/XmlNodeConverterTest.cs | 19 + Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs | 538 ++++++++++++++++++ .../Newtonsoft.Json.Tests.Net35.csproj | 1 + .../Newtonsoft.Json.Tests.Net40.csproj | 1 + .../Newtonsoft.Json.Tests.Portable.csproj | 1 + .../Newtonsoft.Json.Tests.Portable40.csproj | 1 + .../Newtonsoft.Json.Tests.csproj | 1 + .../Properties/AssemblyInfo.cs | 2 +- Src/Newtonsoft.Json/Linq/JArray.cs | 12 + Src/Newtonsoft.Json/Linq/JConstructor.cs | 12 + Src/Newtonsoft.Json/Linq/JContainer.cs | 106 +++- Src/Newtonsoft.Json/Linq/JObject.cs | 34 ++ Src/Newtonsoft.Json/Linq/JProperty.cs | 10 + Src/Newtonsoft.Json/Linq/JsonMergeSettings.cs | 28 + .../Linq/MergeArrayHandling.cs | 20 + .../Newtonsoft.Json.Net20.csproj | 2 + .../Newtonsoft.Json.Net35.csproj | 2 + .../Newtonsoft.Json.Net40.csproj | 2 + .../Newtonsoft.Json.Portable.csproj | 2 + .../Newtonsoft.Json.Portable40.csproj | 2 + Src/Newtonsoft.Json/Newtonsoft.Json.csproj | 2 + .../Properties/AssemblyInfo.cs | 2 +- 22 files changed, 796 insertions(+), 4 deletions(-) create mode 100644 Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs create mode 100644 Src/Newtonsoft.Json/Linq/JsonMergeSettings.cs create mode 100644 Src/Newtonsoft.Json/Linq/MergeArrayHandling.cs diff --git a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs index 1609587f..d89f11e2 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs @@ -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(json); + + Assert.IsNull(foo2.Bar); + } +#endif + [Test] public void SerializeXmlElement() { diff --git a/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs b/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs new file mode 100644 index 00000000..352fb1b7 --- /dev/null +++ b/Src/Newtonsoft.Json.Tests/Linq/MergeTests.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj index 9048f3c5..ba48e820 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj @@ -136,6 +136,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj index 74e48e74..356e47d8 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj @@ -257,6 +257,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj index 2b6cf263..e06c8aa4 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj @@ -141,6 +141,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable40.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable40.csproj index 683dbbc1..b0b00751 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable40.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable40.csproj @@ -138,6 +138,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj index daad7435..81ace437 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj @@ -227,6 +227,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index 31519b7e..8101b3c0 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.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")] diff --git a/Src/Newtonsoft.Json/Linq/JArray.cs b/Src/Newtonsoft.Json/Linq/JArray.cs index adebfd00..b347eab9 100644 --- a/Src/Newtonsoft.Json/Linq/JArray.cs +++ b/Src/Newtonsoft.Json/Linq/JArray.cs @@ -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 Members /// /// Determines the index of a specific item in the . diff --git a/Src/Newtonsoft.Json/Linq/JConstructor.cs b/Src/Newtonsoft.Json/Linq/JConstructor.cs index d9b8acee..b267393a 100644 --- a/Src/Newtonsoft.Json/Linq/JConstructor.cs +++ b/Src/Newtonsoft.Json/Linq/JConstructor.cs @@ -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); + } + /// /// Gets or sets the name of this constructor. /// diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs index c42c5b12..55287518 100644 --- a/Src/Newtonsoft.Json/Linq/JContainer.cs +++ b/Src/Newtonsoft.Json/Linq/JContainer.cs @@ -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); + + /// + /// Merge the specified content into this . + /// + /// The content to be merged. + public void Merge(object content) + { + MergeItem(content, new JsonMergeSettings()); + } + + /// + /// Merge the specified content into this using . + /// + /// The content to be merged. + /// The used to merge the content. + 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 items = new HashSet(target, EqualityComparer); + + foreach (JToken item in content) + { + if (items.Add(item)) + { + target.Add(item); + } + } +#else + IDictionary items = new Dictionary(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."); + } + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 6bb4bb4b..0ef4b0ea 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -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 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); diff --git a/Src/Newtonsoft.Json/Linq/JProperty.cs b/Src/Newtonsoft.Json/Linq/JProperty.cs index 927bb7a4..5051eb8c 100644 --- a/Src/Newtonsoft.Json/Linq/JProperty.cs +++ b/Src/Newtonsoft.Json/Linq/JProperty.cs @@ -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))); diff --git a/Src/Newtonsoft.Json/Linq/JsonMergeSettings.cs b/Src/Newtonsoft.Json/Linq/JsonMergeSettings.cs new file mode 100644 index 00000000..3f33c6a3 --- /dev/null +++ b/Src/Newtonsoft.Json/Linq/JsonMergeSettings.cs @@ -0,0 +1,28 @@ +using System; + +namespace Newtonsoft.Json.Linq +{ + /// + /// Specifies the settings used when merging JSON. + /// + public class JsonMergeSettings + { + private MergeArrayHandling _mergeArrayHandling; + + /// + /// Gets or sets the method used when merging JSON arrays. + /// + /// The method used when merging JSON arrays. + public MergeArrayHandling MergeArrayHandling + { + get { return _mergeArrayHandling; } + set + { + if (value < MergeArrayHandling.Concat || value > MergeArrayHandling.Merge) + throw new ArgumentOutOfRangeException("value"); + + _mergeArrayHandling = value; + } + } + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Linq/MergeArrayHandling.cs b/Src/Newtonsoft.Json/Linq/MergeArrayHandling.cs new file mode 100644 index 00000000..8055dc2f --- /dev/null +++ b/Src/Newtonsoft.Json/Linq/MergeArrayHandling.cs @@ -0,0 +1,20 @@ +namespace Newtonsoft.Json.Linq +{ + /// + /// Specifies how JSON arrays are merged together. + /// + public enum MergeArrayHandling + { + /// Concatenate arrays. + Concat, + + /// Union arrays, skipping items that already exist. + Union, + + /// Replace all array items. + Replace, + + /// Merge array items together, matched by index. + Merge + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj index 6f895040..0e7c6d57 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj @@ -107,6 +107,7 @@ + @@ -117,6 +118,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj index 708b4602..56acebba 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj @@ -119,6 +119,7 @@ + @@ -129,6 +130,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj index 44bb323d..fca9d44b 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj @@ -120,6 +120,7 @@ + @@ -130,6 +131,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj index db92f78a..5d03794b 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj @@ -112,6 +112,7 @@ + @@ -128,6 +129,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj index 905479b0..30e2c739 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj @@ -117,6 +117,7 @@ + @@ -133,6 +134,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj index a20174f6..7566a596 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj @@ -112,6 +112,7 @@ + @@ -132,6 +133,7 @@ + diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index aaefbf6d..d0b29931 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.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)]