diff --git a/Doc/SerializationAttributes.aml b/Doc/SerializationAttributes.aml
index 9ade3aed..e3a90f2e 100644
--- a/Doc/SerializationAttributes.aml
+++ b/Doc/SerializationAttributes.aml
@@ -49,10 +49,11 @@
serialized by default but can be ignored with the JsonIgnoreAttribute, Json.NET's default behavior) or
fields (all public and private fields are serialized and properties are ignored).
Json.NET serializes .NET classes that implement IEnumerable as a JSON array populated with the
- IEnumerable values. Placing the JsonPropertyAttribute overrides this behavior and forces the serializer
- to serialize the class's fields and properties.
- The DataContractAttribute can be used as substitute for JsonObjectAttribute. The
- DataContractAttribute will default member serialization to opt-in.
+ IEnumerable values. Placing the T:Newtonsoft.Json.JsonObjectAttribute
+ overrides this behavior and forces the serializer to serialize the class's fields and properties.
+ The T:System.Runtime.Serialization.DataContractAttribute
+ can be used as substitute for JsonObjectAttribute. The DataContractAttribute will default member
+ serialization to opt-in.
diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs
index db891888..afa1b790 100644
--- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs
@@ -3248,6 +3248,55 @@ null//comment
},
"Unexpected character encountered while parsing value: !. Path 'frameworks.dnxcore50.dependencies.['System.Xml.ReaderWriter'].source', line 6, position 21.");
}
+
+ [Test]
+ [Ignore("Fix this next major version")]
+ public void LinePositionOnNewLine()
+ {
+ string json1 = "{'a':'bc'}";
+
+ JsonTextReader r = new JsonTextReader(new StringReader(json1));
+
+ Assert.IsTrue(r.Read());
+ Assert.AreEqual(1, r.LineNumber);
+ Assert.AreEqual(1, r.LinePosition);
+
+ Assert.IsTrue(r.Read());
+ Assert.AreEqual(1, r.LineNumber);
+ Assert.AreEqual(5, r.LinePosition);
+
+ Assert.IsTrue(r.Read());
+ Assert.AreEqual(1, r.LineNumber);
+ Assert.AreEqual(9, r.LinePosition);
+
+ Assert.IsTrue(r.Read());
+ Assert.AreEqual(1, r.LineNumber);
+ Assert.AreEqual(10, r.LinePosition);
+
+ Assert.IsFalse(r.Read());
+
+ string json2 = "\n{'a':'bc'}";
+
+ r = new JsonTextReader(new StringReader(json2));
+
+ Assert.IsTrue(r.Read());
+ Assert.AreEqual(2, r.LineNumber);
+ Assert.AreEqual(1, r.LinePosition);
+
+ Assert.IsTrue(r.Read());
+ Assert.AreEqual(2, r.LineNumber);
+ Assert.AreEqual(5, r.LinePosition);
+
+ Assert.IsTrue(r.Read());
+ Assert.AreEqual(2, r.LineNumber);
+ Assert.AreEqual(9, r.LinePosition);
+
+ Assert.IsTrue(r.Read());
+ Assert.AreEqual(2, r.LineNumber);
+ Assert.AreEqual(10, r.LinePosition);
+
+ Assert.IsFalse(r.Read());
+ }
}
public class ToggleReaderError : TextReader
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
index 3bf026a8..d87b2923 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
@@ -456,6 +456,7 @@
+
diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
index a75ea035..b0696653 100644
--- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
+++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
@@ -95,6 +95,111 @@ namespace Newtonsoft.Json.Tests.Serialization
[TestFixture]
public class JsonSerializerTest : TestFixtureBase
{
+ public interface ISubclassBase
+ {
+ int ID { get; set; }
+ string Name { get; set; }
+ bool P1 { get; }
+ }
+ public interface ISubclass : ISubclassBase
+ {
+ new bool P1 { get; set; }
+ int P2 { get; set; }
+ }
+ public interface IMainClass
+ {
+ int ID { get; set; }
+ string Name { get; set; }
+ ISubclass Subclass { get; set; }
+ }
+
+ public class Subclass : ISubclass
+ {
+ public int ID { get; set; }
+ public string Name { get; set; }
+ public bool P1 { get; set; }
+ public int P2 { get; set; }
+ }
+ public class MainClass : IMainClass
+ {
+ public int ID { get; set; }
+ public string Name { get; set; }
+ public ISubclass Subclass { get; set; }
+ }
+
+ public class MyFactory
+ {
+ public static ISubclass InstantiateSubclass()
+ {
+ return new Subclass
+ {
+ ID = 123,
+ Name = "ABC",
+ P1 = true,
+ P2 = 44
+ };
+ }
+ public static IMainClass InstantiateManiClass()
+ {
+ return new MainClass
+ {
+ ID = 567,
+ Name = "XYZ",
+ Subclass = InstantiateSubclass()
+ };
+ }
+ }
+
+ [Test]
+ public void SerializeInterfaceWithHiddenProperties()
+ {
+ var mySubclass = MyFactory.InstantiateSubclass();
+ var myMainClass = MyFactory.InstantiateManiClass();
+
+ //Class implementing interface with hidden members - flat object.
+ var strJsonSubclass = JsonConvert.SerializeObject(mySubclass, Formatting.Indented);
+
+ StringAssert.AreEqual(@"{
+ ""ID"": 123,
+ ""Name"": ""ABC"",
+ ""P1"": true,
+ ""P2"": 44
+}", strJsonSubclass);
+
+ //Class implementing interface with hidden members - member of another class.
+ var strJsonMainClass = JsonConvert.SerializeObject(myMainClass, Formatting.Indented);
+
+ StringAssert.AreEqual(@"{
+ ""ID"": 567,
+ ""Name"": ""XYZ"",
+ ""Subclass"": {
+ ""ID"": 123,
+ ""Name"": ""ABC"",
+ ""P1"": true,
+ ""P2"": 44
+ }
+}", strJsonMainClass);
+ }
+
+ [Test]
+ public void LargeIntegerAsString()
+ {
+ Console.WriteLine("Sending in: \n43443333222211111117");
+ var largeBrokenNumber = JsonConvert.DeserializeObject("{\"Blah\": 43443333222211111117 }");
+ Console.WriteLine(largeBrokenNumber.Blah);
+
+ Console.WriteLine();
+
+ Console.WriteLine("Sending in: \n53443333222211111117");
+ var largeOddWorkingNumber = JsonConvert.DeserializeObject("{\"Blah\": 53443333222211111117 }");
+ Console.WriteLine(largeOddWorkingNumber.Blah);
+ }
+
+ public class Foo64
+ {
+ public string Blah { get; set; }
+ }
+
[Test]
public void CaseInsensitiveRequiredPropertyConstructorCreation()
{
diff --git a/Src/Newtonsoft.Json.Tests/Utilities/ConvertUtilsTests.cs b/Src/Newtonsoft.Json.Tests/Utilities/ConvertUtilsTests.cs
new file mode 100644
index 00000000..770f857c
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Utilities/ConvertUtilsTests.cs
@@ -0,0 +1,130 @@
+#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
+
+#if NETFX_CORE
+using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
+using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
+using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
+#elif DNXCORE50
+using Xunit;
+using Test = Xunit.FactAttribute;
+using Assert = Newtonsoft.Json.Tests.XUnitAssert;
+#else
+using NUnit.Framework;
+#endif
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Tests.Utilities
+{
+ [TestFixture]
+ public class ConvertUtilsTests : TestFixtureBase
+ {
+ [Test]
+ public void Int64TryParse()
+ {
+ long l;
+ char[] c = "43443333222211111117".ToCharArray();
+ ParseResult result = ConvertUtils.Int64TryParse(c, 0, c.Length, out l);
+ Assert.AreEqual(ParseResult.Overflow, result);
+
+ c = "9223372036854775807".ToCharArray();
+ result = ConvertUtils.Int64TryParse(c, 0, c.Length, out l);
+ Assert.AreEqual(ParseResult.Success, result);
+ Assert.AreEqual(9223372036854775807L, l);
+
+ c = "9223372036854775808".ToCharArray();
+ result = ConvertUtils.Int64TryParse(c, 0, c.Length, out l);
+ Assert.AreEqual(ParseResult.Overflow, result);
+
+ for (int i = 3; i < 10; i++)
+ {
+ c = ("9" + i + "23372036854775807").ToCharArray();
+ result = ConvertUtils.Int64TryParse(c, 0, c.Length, out l);
+ Assert.AreEqual(ParseResult.Overflow, result);
+ }
+
+
+
+ c = "-9223372036854775808".ToCharArray();
+ result = ConvertUtils.Int64TryParse(c, 0, c.Length, out l);
+ Assert.AreEqual(ParseResult.Success, result);
+ Assert.AreEqual(-9223372036854775808L, l);
+
+ c = "-9223372036854775809".ToCharArray();
+ result = ConvertUtils.Int64TryParse(c, 0, c.Length, out l);
+ Assert.AreEqual(ParseResult.Overflow, result);
+
+ for (int i = 3; i < 10; i++)
+ {
+ c = ("-9" + i + "23372036854775808").ToCharArray();
+ result = ConvertUtils.Int64TryParse(c, 0, c.Length, out l);
+ Assert.AreEqual(ParseResult.Overflow, result);
+ }
+ }
+
+ [Test]
+ public void Int32TryParse()
+ {
+ int i;
+ char[] c = "43443333227".ToCharArray();
+ ParseResult result = ConvertUtils.Int32TryParse(c, 0, c.Length, out i);
+ Assert.AreEqual(ParseResult.Overflow, result);
+
+ c = "2147483647".ToCharArray();
+ result = ConvertUtils.Int32TryParse(c, 0, c.Length, out i);
+ Assert.AreEqual(ParseResult.Success, result);
+ Assert.AreEqual(2147483647, i);
+
+ c = "2147483648".ToCharArray();
+ result = ConvertUtils.Int32TryParse(c, 0, c.Length, out i);
+ Assert.AreEqual(ParseResult.Overflow, result);
+
+ for (int j = 2; j < 10; j++)
+ {
+ c = ("2" + j + "47483647").ToCharArray();
+ result = ConvertUtils.Int32TryParse(c, 0, c.Length, out i);
+ Assert.AreEqual(ParseResult.Overflow, result);
+ }
+
+
+
+ c = "-2147483648".ToCharArray();
+ result = ConvertUtils.Int32TryParse(c, 0, c.Length, out i);
+ Assert.AreEqual(ParseResult.Success, result);
+ Assert.AreEqual(-2147483648, i);
+
+ c = "-2147483649".ToCharArray();
+ result = ConvertUtils.Int32TryParse(c, 0, c.Length, out i);
+ Assert.AreEqual(ParseResult.Overflow, result);
+
+ for (int j = 3; j < 10; j++)
+ {
+ c = ("-2" + j + "47483648").ToCharArray();
+ result = ConvertUtils.Int32TryParse(c, 0, c.Length, out i);
+ Assert.AreEqual(ParseResult.Overflow, result);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs b/Src/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs
index c49a07cf..ea9ee82d 100644
--- a/Src/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs
+++ b/Src/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs
@@ -50,7 +50,7 @@ namespace Newtonsoft.Json.Serialization
/// The property name camel cased.
protected override string ResolvePropertyName(string propertyName)
{
- // lower case the first letter of the passed in name
+ // lower case the first letter (or more) of the passed in name
return StringUtils.ToCamelCase(propertyName);
}
}
diff --git a/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs b/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs
index 406f4b8d..dd684942 100644
--- a/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs
+++ b/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs
@@ -85,13 +85,15 @@ namespace Newtonsoft.Json.Serialization
{
if (property.DeclaringType != null && existingProperty.DeclaringType != null)
{
- if (property.DeclaringType.IsSubclassOf(existingProperty.DeclaringType))
+ if (property.DeclaringType.IsSubclassOf(existingProperty.DeclaringType)
+ || (existingProperty.DeclaringType.IsInterface && property.DeclaringType.ImplementInterface(existingProperty.DeclaringType)))
{
// current property is on a derived class and hides the existing
Remove(existingProperty);
duplicateProperty = false;
}
- if (existingProperty.DeclaringType.IsSubclassOf(property.DeclaringType))
+ if (existingProperty.DeclaringType.IsSubclassOf(property.DeclaringType)
+ || (property.DeclaringType.IsInterface && existingProperty.DeclaringType.ImplementInterface(property.DeclaringType)))
{
// current property is hidden by the existing so don't add it
return;
diff --git a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs
index e27d9a13..f3fa5cab 100644
--- a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs
+++ b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs
@@ -665,6 +665,21 @@ namespace Newtonsoft.Json.Utilities
int end = start + length;
+ // Int32.MaxValue and MinValue are 10 chars
+ if (length > 10)
+ {
+ // invalid result takes precedence over overflow
+ for (int i = start; i < end; i++)
+ {
+ int c = chars[i] - '0';
+
+ if (c < 0 || c > 9)
+ return ParseResult.Invalid;
+ }
+
+ return ParseResult.Overflow;
+ }
+
for (int i = start; i < end; i++)
{
int c = chars[i] - '0';
@@ -730,6 +745,21 @@ namespace Newtonsoft.Json.Utilities
int end = start + length;
+ // Int64.MaxValue and MinValue are 19 chars
+ if (length > 19)
+ {
+ // invalid result takes precedence over overflow
+ for (int i = start; i < end; i++)
+ {
+ int c = chars[i] - '0';
+
+ if (c < 0 || c > 9)
+ return ParseResult.Invalid;
+ }
+
+ return ParseResult.Overflow;
+ }
+
for (int i = start; i < end; i++)
{
int c = chars[i] - '0';
diff --git a/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs b/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs
index 96472ca0..e4bd1149 100644
--- a/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs
+++ b/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs
@@ -550,5 +550,23 @@ namespace Newtonsoft.Json.Utilities
Type match;
return type.AssignableToTypeName(fullTypeName, out match);
}
+
+ public static bool ImplementInterface(this Type type, Type interfaceType)
+ {
+ for (Type currentType = type; currentType != null; currentType = currentType.BaseType)
+ {
+ Type[] interfaces = currentType.GetInterfaces();
+
+ for (int i = 0; i < interfaces.Length; i++)
+ {
+ if (interfaces[i] == interfaceType || (interfaces[i] != null && interfaces[i].ImplementInterface(interfaceType)))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
}
}
\ No newline at end of file