diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs
index 3595ae4b..81a497a9 100644
--- a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs
@@ -29,6 +29,7 @@ using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;
using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Tests.TestObjects;
#if !(NET20 || NET35 || PORTABLE)
using System.Numerics;
#endif
diff --git a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs
index 619636b4..c6b07a8c 100644
--- a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs
+++ b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs
@@ -115,6 +115,22 @@ namespace Newtonsoft.Json.Tests.Converters
}
#if !NET20
+ [Test]
+ public void GroupElementsOfTheSameName()
+ {
+ string xml = "Text1Span1 Span2 Text2
";
+
+ string json = JsonConvert.SerializeXNode(XElement.Parse(xml));
+
+ Assert.AreEqual(@"{""root"":{""p"":{""#text"":[""Text1"","" Text2""],""span"":[""Span1"",""Span2""]}}}", json);
+
+ XDocument doc = JsonConvert.DeserializeXNode(json);
+
+ Assert.AreEqual(@"
+ Text1 Text2Span1Span2
+", doc.ToString());
+ }
+
[Test]
public void SerializeEmptyDocument()
{
diff --git a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Schema/JTokenIsValid.cs b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Schema/JTokenIsValid.cs
index f3063b57..5844862e 100644
--- a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Schema/JTokenIsValid.cs
+++ b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Schema/JTokenIsValid.cs
@@ -13,7 +13,6 @@ namespace Newtonsoft.Json.Tests.Documentation.Samples.Schema
{
#region Usage
JsonSchema schema = JsonSchema.Parse(@"{
- 'description': 'A person',
'type': 'object',
'properties': {
'name': {'type':'string'},
@@ -29,7 +28,8 @@ namespace Newtonsoft.Json.Tests.Documentation.Samples.Schema
'hobbies': ['.NET', 'Blogging', 'Reading', 'Xbox', 'LOLCATS']
}");
- bool valid = person.IsValid(schema);
+ IList errorMessages;
+ bool valid = person.IsValid(schema, out errorMessages);
Console.WriteLine(valid);
// true
diff --git a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
index 34f4d5f2..9e32bea3 100644
--- a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
@@ -952,7 +952,7 @@ now brown cow?", '"', true);
#pragma warning disable 612,618
Task taskVoid = JsonConvert.PopulateObjectAsync("{'Name':'Appended'}", p, new JsonSerializerSettings
{
- Converters = new List { new JsonSerializerTest.StringAppenderConverter() }
+ Converters = new List { new StringAppenderConverter() }
});
#pragma warning restore 612,618
diff --git a/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs
index 1017ea95..d7975c89 100644
--- a/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs
@@ -26,6 +26,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using Newtonsoft.Json.Tests.TestObjects;
#if !(NET20 || NET35 || PORTABLE)
using System.Numerics;
#endif
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj
index bd3693d7..dbe0165e 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj
@@ -98,15 +98,24 @@
+
+
+
+
+
+
+
+
+
@@ -116,38 +125,59 @@
Component
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -157,6 +187,7 @@
+
@@ -237,11 +268,21 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj
index 05633c52..760b968e 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj
@@ -140,16 +140,24 @@
+
+
+
+
+
+
+
+
@@ -158,15 +166,34 @@
Component
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -199,8 +226,15 @@
+
+
+
+
+
+
+
@@ -285,6 +319,12 @@
+
+
+
+
+
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj
index d7fa9a92..f1e9baa4 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj
@@ -262,16 +262,24 @@
+
+
+
+
+
+
+
+
@@ -280,15 +288,33 @@
Component
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -317,12 +343,20 @@
+
+
+
+
+
+
+
+
@@ -407,6 +441,12 @@
+
+
+
+
+
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj
index 73528136..667ead78 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj
@@ -146,31 +146,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -199,12 +225,20 @@
+
+
+
+
+
+
+
+
@@ -289,6 +323,12 @@
+
+
+
+
+
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable40.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable40.csproj
index e3293651..76808865 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable40.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable40.csproj
@@ -142,29 +142,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -193,12 +221,20 @@
+
+
+
+
+
+
+
+
@@ -283,6 +319,12 @@
+
+
+
+
+
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
index fee4e78f..c28811c6 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
@@ -237,6 +237,7 @@
+
@@ -248,17 +249,23 @@
+
+
+
+
+
+
@@ -266,6 +273,7 @@
+
@@ -279,25 +287,35 @@
Component
+
+
+
+
+
+
+
+
+
+
@@ -311,17 +329,25 @@
+
+
+
+
+
+
+
+
@@ -331,14 +357,18 @@
+
+
+
+
@@ -351,11 +381,21 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
index 3ee5554b..91ba79cf 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.1.17117")]
+[assembly: AssemblyFileVersion("6.0.1.17131")]
diff --git a/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs b/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs
index 0f31119d..d9c40421 100644
--- a/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs
@@ -308,6 +308,16 @@ namespace Newtonsoft.Json.Tests.Schema
});
}
+ [Test]
+ public void DivisibleBy_Approx()
+ {
+ JsonSchema schema = new JsonSchema();
+ schema.DivisibleBy = 0.01;
+
+ JValue v = new JValue(20.49);
+ v.Validate(schema);
+ }
+
[Test]
public void UniqueItems_SimpleUnique()
{
diff --git a/Src/Newtonsoft.Json.Tests/Serialization/ExtensionDataTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/ExtensionDataTests.cs
new file mode 100644
index 00000000..f9f3535a
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Serialization/ExtensionDataTests.cs
@@ -0,0 +1,599 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Tests.TestObjects;
+using NUnit.Framework;
+
+namespace Newtonsoft.Json.Tests.Serialization
+{
+ [TestFixture]
+ public class ExtensionDataTests : TestFixtureBase
+ {
+ public class ExtensionDataDeserializeWithNonDefaultConstructor
+ {
+ public ExtensionDataDeserializeWithNonDefaultConstructor(string name)
+ {
+ Name = name;
+ }
+
+ [JsonExtensionData]
+ public IDictionary _extensionData;
+
+ public string Name { get; set; }
+ }
+
+ [Test]
+ public void ExtensionDataDeserializeWithNonDefaultConstructorTest()
+ {
+ ExtensionDataDeserializeWithNonDefaultConstructor c = new ExtensionDataDeserializeWithNonDefaultConstructor("Name!");
+ c._extensionData = new Dictionary
+ {
+ { "Key!", "Value!" }
+ };
+
+ string json = JsonConvert.SerializeObject(c, Formatting.Indented);
+
+ Assert.AreEqual(@"{
+ ""Name"": ""Name!"",
+ ""Key!"": ""Value!""
+}", json);
+
+ var c2 = JsonConvert.DeserializeObject(json);
+
+ Assert.AreEqual("Name!", c2.Name);
+ Assert.IsNotNull(c2._extensionData);
+ Assert.AreEqual(1, c2._extensionData.Count);
+ Assert.AreEqual("Value!", (string)c2._extensionData["Key!"]);
+ }
+
+ [Test]
+ public void ExtensionDataWithNull()
+ {
+ string json = @"{
+ 'TaxRate': 0.125,
+ 'a':null
+ }";
+
+ var invoice = JsonConvert.DeserializeObject(json);
+
+ Assert.AreEqual(JTokenType.Null, invoice._additionalData["a"].Type);
+ Assert.AreEqual(typeof(double), ((JValue)invoice._additionalData["TaxRate"]).Value.GetType());
+
+ string result = JsonConvert.SerializeObject(invoice);
+
+ Assert.AreEqual(@"{""TaxRate"":0.125,""a"":null}", result);
+ }
+
+ [Test]
+ public void ExtensionDataFloatParseHandling()
+ {
+ string json = @"{
+ 'TaxRate': 0.125,
+ 'a':null
+ }";
+
+ var invoice = JsonConvert.DeserializeObject(json, new JsonSerializerSettings
+ {
+ FloatParseHandling = FloatParseHandling.Decimal
+ });
+
+ Assert.AreEqual(typeof(decimal), ((JValue)invoice._additionalData["TaxRate"]).Value.GetType());
+ }
+
+#pragma warning disable 649
+ class ExtendedObject
+ {
+ [JsonExtensionData]
+ internal IDictionary _additionalData;
+ }
+#pragma warning restore 649
+
+#pragma warning disable 169
+ public class CustomerInvoice
+ {
+ // we're only modifing the tax rate
+ public decimal TaxRate { get; set; }
+
+ // everything else gets stored here
+ [JsonExtensionData]
+ private IDictionary _additionalData;
+ }
+#pragma warning restore 169
+
+ [Test]
+ public void ExtensionDataExample()
+ {
+ string json = @"{
+ 'HourlyRate': 150,
+ 'Hours': 40,
+ 'TaxRate': 0.125
+ }";
+
+ var invoice = JsonConvert.DeserializeObject(json);
+
+ // increase tax to 15%
+ invoice.TaxRate = 0.15m;
+
+ string result = JsonConvert.SerializeObject(invoice);
+ // {
+ // 'TaxRate': 0.15,
+ // 'HourlyRate': 150,
+ // 'Hours': 40
+ // }
+
+ Assert.AreEqual(@"{""TaxRate"":0.15,""HourlyRate"":150,""Hours"":40}", result);
+ }
+
+ public class ExtensionDataTestClass
+ {
+ public string Name { get; set; }
+
+ [JsonProperty("custom_name")]
+ public string CustomName { get; set; }
+
+ [JsonIgnore]
+ public IList Ignored { get; set; }
+
+ public bool GetPrivate { get; internal set; }
+
+ public bool GetOnly
+ {
+ get { return true; }
+ }
+
+ public readonly string Readonly = "Readonly";
+ public IList Ints { get; set; }
+
+ [JsonExtensionData]
+ internal IDictionary ExtensionData { get; set; }
+
+ public ExtensionDataTestClass()
+ {
+ Ints = new List { 0 };
+ }
+ }
+
+ public class JObjectExtensionDataTestClass
+ {
+ public string Name { get; set; }
+
+ [JsonExtensionData]
+ public JObject ExtensionData { get; set; }
+ }
+
+ [Test]
+ public void RoundTripJObjectExtensionData()
+ {
+ JObjectExtensionDataTestClass c = new JObjectExtensionDataTestClass();
+ c.Name = "Name!";
+ c.ExtensionData = new JObject
+ {
+ { "one", 1 },
+ { "two", "II" },
+ { "three", new JArray(1, 1, 1) }
+ };
+
+ string json = JsonConvert.SerializeObject(c, Formatting.Indented);
+
+ JObjectExtensionDataTestClass c2 = JsonConvert.DeserializeObject(json);
+
+ Assert.AreEqual("Name!", c2.Name);
+ Assert.IsTrue(JToken.DeepEquals(c.ExtensionData, c2.ExtensionData));
+ }
+
+ [Test]
+ public void ExtensionDataTest()
+ {
+ string json = @"{
+ ""Ints"": [1,2,3],
+ ""Ignored"": [1,2,3],
+ ""Readonly"": ""Readonly"",
+ ""Name"": ""Actually set!"",
+ ""CustomName"": ""Wrong name!"",
+ ""GetPrivate"": true,
+ ""GetOnly"": true,
+ ""NewValueSimple"": true,
+ ""NewValueComplex"": [1,2,3]
+}";
+
+ ExtensionDataTestClass c = JsonConvert.DeserializeObject(json);
+
+ Assert.AreEqual("Actually set!", c.Name);
+ Assert.AreEqual(4, c.Ints.Count);
+
+ Assert.AreEqual("Readonly", (string)c.ExtensionData["Readonly"]);
+ Assert.AreEqual("Wrong name!", (string)c.ExtensionData["CustomName"]);
+ Assert.AreEqual(true, (bool)c.ExtensionData["GetPrivate"]);
+ Assert.AreEqual(true, (bool)c.ExtensionData["GetOnly"]);
+ Assert.AreEqual(true, (bool)c.ExtensionData["NewValueSimple"]);
+ Assert.IsTrue(JToken.DeepEquals(new JArray(1, 2, 3), c.ExtensionData["NewValueComplex"]));
+ Assert.IsTrue(JToken.DeepEquals(new JArray(1, 2, 3), c.ExtensionData["Ignored"]));
+
+ Assert.AreEqual(7, c.ExtensionData.Count);
+ }
+
+ public class MultipleExtensionDataAttributesTestClass
+ {
+ public string Name { get; set; }
+
+ [JsonExtensionData]
+ internal IDictionary ExtensionData1 { get; set; }
+
+ [JsonExtensionData]
+ internal IDictionary ExtensionData2 { get; set; }
+ }
+
+ public class ExtensionDataAttributesInheritanceTestClass : MultipleExtensionDataAttributesTestClass
+ {
+ [JsonExtensionData]
+ internal IDictionary ExtensionData0 { get; set; }
+ }
+
+ public class FieldExtensionDataAttributeTestClass
+ {
+ [JsonExtensionData]
+ internal IDictionary