diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs index 5dc7def5..845ed140 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs @@ -25,6 +25,9 @@ using System; using System.Globalization; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using System.Text; #if !NETFX_CORE using NUnit.Framework; @@ -1313,5 +1316,29 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(badText, (string)o["test"]); } #endif + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + public class BigIntegerTestClass + { + public BigInteger Blah { get; set; } + } + + [Test] + public void WriteBigInteger() + { + BigInteger i = BigInteger.Parse("1999999999999999999999999999999999999999999999999999999999990"); + + byte[] data = MiscellaneousUtils.HexToBytes("2A-00-00-00-05-42-6C-61-68-00-1A-00-00-00-00-F6-FF-FF-FF-FF-FF-FF-1F-B2-21-CB-28-59-84-C4-AE-03-8A-44-34-2F-4C-4E-9E-3E-01-00"); + MemoryStream ms = new MemoryStream(data); + + BsonReader reader = new BsonReader(ms); + + JsonSerializer serializer = new JsonSerializer(); + + BigIntegerTestClass c = serializer.Deserialize(reader); + + Assert.AreEqual(i, c.Blah); + } +#endif } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs index bfddc694..edbaae08 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs @@ -25,6 +25,9 @@ using System; using System.Collections.Generic; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using System.Text; #if !NETFX_CORE using NUnit.Framework; @@ -680,5 +683,42 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual("10-00-00-00-09-30-00-C8-88-07-6B-DC-00-00-00-00", (BitConverter.ToString(ms.ToArray()))); } + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + [Test] + public void WriteBigInteger() + { + BigInteger i = BigInteger.Parse("1999999999999999999999999999999999999999999999999999999999990"); + + MemoryStream ms = new MemoryStream(); + BsonWriter writer = new BsonWriter(ms); + + writer.WriteStartObject(); + writer.WritePropertyName("Blah"); + writer.WriteValue(i); + writer.WriteEndObject(); + + string bson = MiscellaneousUtils.BytesToHex(ms.ToArray()); + Assert.AreEqual("2A-00-00-00-05-42-6C-61-68-00-1A-00-00-00-00-F6-FF-FF-FF-FF-FF-FF-1F-B2-21-CB-28-59-84-C4-AE-03-8A-44-34-2F-4C-4E-9E-3E-01-00", bson); + + ms.Seek(0, SeekOrigin.Begin); + BsonReader reader = new BsonReader(ms); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.StartObject, reader.TokenType); + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Bytes, reader.TokenType); + Assert.AreEqual(new byte[] { 246, 255, 255, 255, 255, 255, 255, 31, 178, 33, 203, 40, 89, 132, 196, 174, 3, 138, 68, 52, 47, 76, 78, 158, 62, 1 }, reader.Value); + Assert.AreEqual(i, new BigInteger((byte[])reader.Value)); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.EndObject, reader.TokenType); + + Assert.IsFalse(reader.Read()); + } +#endif } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs b/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs index f38019f5..07d684fe 100644 --- a/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs +++ b/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs @@ -29,6 +29,9 @@ using System.IO; #if NET20 using Newtonsoft.Json.Utilities.LinqBridge; #endif +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using System.Text; #if !NETFX_CORE using NUnit.Framework; @@ -39,6 +42,7 @@ using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAtt #endif using System.Xml; using System.Xml.Schema; +using Newtonsoft.Json.Linq; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Utilities; using ValidationEventArgs = Newtonsoft.Json.Schema.ValidationEventArgs; @@ -348,6 +352,51 @@ namespace Newtonsoft.Json.Tests Assert.IsNotNull(validationEventArgs); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + [Test] + public void IntegerGreaterThanMaximumValue_BigInteger() + { + string schemaJson = @"{ + ""type"":""integer"", + ""maximum"":5 +}"; + + string json = "99999999999999999999999999999999999999999999999999999999999999999999"; + + Json.Schema.ValidationEventArgs validationEventArgs = null; + + JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json))); + reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; }; + reader.Schema = JsonSchema.Parse(schemaJson); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Integer, reader.TokenType); + Assert.AreEqual("Integer 99999999999999999999999999999999999999999999999999999999999999999999 exceeds maximum value of 5. Line 1, position 68.", validationEventArgs.Message); + Assert.AreEqual("", validationEventArgs.Path); + + Assert.IsNotNull(validationEventArgs); + } + + [Test] + public void IntegerLessThanMaximumValue_BigInteger() + { + string schemaJson = @"{ + ""type"":""integer"", + ""minimum"":5 +}"; + + JValue v = new JValue(new BigInteger(1)); + + Json.Schema.ValidationEventArgs validationEventArgs = null; + + v.Validate(JsonSchema.Parse(schemaJson), (sender, args) => { validationEventArgs = args; }); + + Assert.IsNotNull(validationEventArgs); + Assert.AreEqual("Integer 1 is less than minimum value of 5.", validationEventArgs.Message); + Assert.AreEqual("", validationEventArgs.Path); + } +#endif + [Test] public void ThrowExceptionWhenNoValidationEventHandler() { @@ -518,7 +567,7 @@ namespace Newtonsoft.Json.Tests } [Test] - public void FloatExceedsMaxDecimalPlaces() + public void FloatDivisibleBy() { string schemaJson = @"{ ""type"":""array"", @@ -557,6 +606,123 @@ namespace Newtonsoft.Json.Tests Assert.IsNotNull(validationEventArgs); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + [Test] + public void BigIntegerDivisibleBy_Success() + { + string schemaJson = @"{ + ""type"":""array"", + ""items"":{ + ""type"":""number"", + ""divisibleBy"":2 + } +}"; + + string json = "[999999999999999999999999999999999999999999999999999999998]"; + + Json.Schema.ValidationEventArgs validationEventArgs = null; + + JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json))); + reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; }; + reader.Schema = JsonSchema.Parse(schemaJson); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.StartArray, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Integer, reader.TokenType); + Assert.IsNull(validationEventArgs); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.EndArray, reader.TokenType); + } + + [Test] + public void BigIntegerDivisibleBy_Failure() + { + string schemaJson = @"{ + ""type"":""array"", + ""items"":{ + ""type"":""number"", + ""divisibleBy"":2 + } +}"; + + string json = "[999999999999999999999999999999999999999999999999999999999]"; + + Json.Schema.ValidationEventArgs validationEventArgs = null; + + JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json))); + reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; }; + reader.Schema = JsonSchema.Parse(schemaJson); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.StartArray, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Integer, reader.TokenType); + Assert.AreEqual(@"Integer 999999999999999999999999999999999999999999999999999999999 is not evenly divisible by 2. Line 1, position 58.", validationEventArgs.Message); + Assert.AreEqual("[0]", validationEventArgs.Path); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.EndArray, reader.TokenType); + + Assert.IsNotNull(validationEventArgs); + } + + [Test] + public void BigIntegerDivisibleBy_Fraction() + { + string schemaJson = @"{ + ""type"":""array"", + ""items"":{ + ""type"":""number"", + ""divisibleBy"":1.1 + } +}"; + + string json = "[999999999999999999999999999999999999999999999999999999999]"; + + Json.Schema.ValidationEventArgs validationEventArgs = null; + + JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json))); + reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; }; + reader.Schema = JsonSchema.Parse(schemaJson); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.StartArray, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.Integer, reader.TokenType); + Assert.IsNotNull(validationEventArgs); + Assert.AreEqual(@"Integer 999999999999999999999999999999999999999999999999999999999 is not evenly divisible by 1.1. Line 1, position 58.", validationEventArgs.Message); + Assert.AreEqual("[0]", validationEventArgs.Path); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.EndArray, reader.TokenType); + } + + [Test] + public void BigIntegerDivisibleBy_FractionWithZeroValue() + { + string schemaJson = @"{ + ""type"":""array"", + ""items"":{ + ""type"":""number"", + ""divisibleBy"":1.1 + } +}"; + + JArray a = new JArray(new JValue(new BigInteger(0))); + + ValidationEventArgs validationEventArgs = null; + + a.Validate(JsonSchema.Parse(schemaJson), (sender, args) => { validationEventArgs = args; }); + + Assert.IsNull(validationEventArgs); + } +#endif + [Test] public void IntValidForNumber() { diff --git a/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs b/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs index eb8d09ab..70c4a6be 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs @@ -28,6 +28,9 @@ using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using System.Text; using Newtonsoft.Json.Linq; #if !NETFX_CORE @@ -175,6 +178,9 @@ namespace Newtonsoft.Json.Tests.Linq new JProperty("Uri", new Uri("http://json.codeplex.com/")), new JProperty("Guid", new Guid("EA27FE1D-0D80-44F2-BF34-4654156FA7AF")), new JProperty("TimeSpan", TimeSpan.FromDays(1)) +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + ,new JProperty("BigInteger", BigInteger.Parse("1")) +#endif ); dynamic d = o; @@ -205,6 +211,9 @@ namespace Newtonsoft.Json.Tests.Linq Assert.IsTrue(d.Decimal == 1.1m); Assert.IsTrue(d.Decimal != 1.0f); Assert.IsTrue(d.Decimal != 1.0d); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + Assert.IsTrue(d.Decimal > new BigInteger(0)); +#endif Assert.IsTrue(d.Float == d.Float); Assert.IsTrue(d.Float > 0); @@ -218,6 +227,24 @@ namespace Newtonsoft.Json.Tests.Linq Assert.IsTrue(d.Float == 1.1m); Assert.IsTrue(d.Float != 1.0f); Assert.IsTrue(d.Float != 1.0d); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + Assert.IsTrue(d.Float > new BigInteger(0)); +#endif + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + Assert.IsTrue(d.BigInteger == d.BigInteger); + Assert.IsTrue(d.BigInteger > 0); + Assert.IsTrue(d.BigInteger > 0.0m); + Assert.IsTrue(d.BigInteger > 0.0f); + Assert.IsTrue(d.BigInteger > null); + Assert.IsTrue(d.BigInteger >= null); + Assert.IsTrue(d.BigInteger < 2); + Assert.IsTrue(d.BigInteger <= 1.1); + Assert.IsTrue(d.BigInteger == 1); + Assert.IsTrue(d.BigInteger == 1m); + Assert.IsTrue(d.BigInteger != 1.1f); + Assert.IsTrue(d.BigInteger != 1.1d); +#endif Assert.IsTrue(d.Bytes == d.Bytes); Assert.IsTrue(d.Bytes == Encoding.UTF8.GetBytes("A string lol!")); @@ -260,6 +287,9 @@ namespace Newtonsoft.Json.Tests.Linq new JProperty("Uri", new Uri("http://json.codeplex.com/")), new JProperty("Guid", new Guid("EA27FE1D-0D80-44F2-BF34-4654156FA7AF")), new JProperty("TimeSpan", TimeSpan.FromDays(1)) +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + ,new JProperty("BigInteger", new BigInteger(100)) +#endif ); dynamic d = o; @@ -335,6 +365,23 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(null, r.Value); r += 2; Assert.AreEqual(null, r.Value); + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + r = d.BigInteger + null; + Assert.AreEqual(null, r.Value); + r += 2; + Assert.AreEqual(null, r.Value); + + r = d.BigInteger + 1; + Assert.AreEqual(101, (int)r); + r += 2; + Assert.AreEqual(103, (int)r); + + r = d.BigInteger + 1.1d; + Assert.AreEqual(101m, (decimal)r); + r += 2; + Assert.AreEqual(103m, (decimal)r); +#endif #endregion #region Subtract @@ -397,6 +444,18 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(null, r.Value); r -= 2; Assert.AreEqual(null, r.Value); + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + r = d.BigInteger - null; + Assert.AreEqual(null, r.Value); + r -= 2; + Assert.AreEqual(null, r.Value); + + r = d.BigInteger - 1.1d; + Assert.AreEqual(99m, (decimal)r); + r -= 2; + Assert.AreEqual(97m, (decimal)r); +#endif #endregion #region Multiply @@ -459,6 +518,18 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(null, r.Value); r *= 2; Assert.AreEqual(null, r.Value); + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + r = d.BigInteger * 1.1d; + Assert.AreEqual(100m, (decimal)r); + r *= 2; + Assert.AreEqual(200m, (decimal)r); + + r = d.BigInteger * null; + Assert.AreEqual(null, r.Value); + r *= 2; + Assert.AreEqual(null, r.Value); +#endif #endregion #region Divide @@ -521,6 +592,18 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(null, r.Value); r /= 2; Assert.AreEqual(null, r.Value); + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + r = d.BigInteger / 1.1d; + Assert.AreEqual(100m, (decimal)r); + r /= 2; + Assert.AreEqual(50m, (decimal)r); + + r = d.BigInteger / null; + Assert.AreEqual(null, r.Value); + r /= 2; + Assert.AreEqual(null, r.Value); +#endif #endregion } @@ -538,6 +621,9 @@ namespace Newtonsoft.Json.Tests.Linq new JProperty("Uri", new Uri("http://json.codeplex.com/")), new JProperty("Guid", new Guid("EA27FE1D-0D80-44F2-BF34-4654156FA7AF")), new JProperty("TimeSpan", TimeSpan.FromDays(1)) +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + ,new JProperty("BigInteger", new BigInteger(100)) +#endif ); dynamic d = o; @@ -552,6 +638,9 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual("http://json.codeplex.com/", d.Uri.ToString()); Assert.AreEqual("ea27fe1d-0d80-44f2-bf34-4654156fa7af", d.Guid.ToString()); Assert.AreEqual("1.00:00:00", d.TimeSpan.ToString()); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + Assert.AreEqual("100", d.BigInteger.ToString()); +#endif } [Test] @@ -633,6 +722,10 @@ namespace Newtonsoft.Json.Tests.Linq AssertValueConverted(null); AssertValueConverted(new Uri("http://json.codeplex.com/")); AssertValueConverted(null); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + AssertValueConverted(new BigInteger(100)); + AssertValueConverted(null); +#endif } private static void AssertValueConverted(object value) diff --git a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs index 7bbf8db3..f37a87c1 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs @@ -27,6 +27,9 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using Newtonsoft.Json.Tests.TestObjects; #if !NETFX_CORE using NUnit.Framework; @@ -1628,17 +1631,17 @@ Parameter name: arrayIndex", }); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) [Test] public void NumberTooBigForInt64() { - ExceptionAssert.Throws("JSON integer 307953220000517141511 is too large or small for an Int64. Path 'code', line 1, position 30.", - () => - { - string json = @"{""code"": 307953220000517141511}"; + string json = @"{""code"": 307953220000517141511}"; - JObject.Parse(json); - }); + JObject o = JObject.Parse(json); + + BigInteger b = (BigInteger)o["code"]; } +#endif [Test] public void ParseIncomplete() diff --git a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs index 49b36c24..cb1fd690 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs @@ -25,6 +25,9 @@ using System; using System.Collections.Generic; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using System.Text; using Newtonsoft.Json.Converters; #if !NETFX_CORE @@ -344,6 +347,29 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(data, (byte[])(new JValue(data))); Assert.AreEqual(5, (int)(new JValue(StringComparison.OrdinalIgnoreCase))); + + string bigIntegerText = "1234567899999999999999999999999999999999999999999999999999999999999990"; + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + Assert.AreEqual(BigInteger.Parse(bigIntegerText), (BigInteger)(new JValue(bigIntegerText))); + Assert.AreEqual(new BigInteger(long.MaxValue), (BigInteger)(new JValue(long.MaxValue))); + Assert.AreEqual(new BigInteger(4.5d), (BigInteger)(new JValue((4.5d)))); + Assert.AreEqual(new BigInteger(4.5f), (BigInteger)(new JValue((4.5f)))); + Assert.AreEqual(new BigInteger(byte.MaxValue), (BigInteger)(new JValue(byte.MaxValue))); + Assert.AreEqual(new BigInteger(123), (BigInteger)(new JValue(123))); + + byte[] intData = BigInteger.Parse(bigIntegerText).ToByteArray(); + Assert.AreEqual(BigInteger.Parse(bigIntegerText), (BigInteger)(new JValue(intData))); + + Assert.AreEqual(4.0d, (double)(new JValue(new BigInteger(4.5d)))); + Assert.AreEqual(true, (bool)(new JValue(new BigInteger(1)))); + Assert.AreEqual(long.MaxValue, (long)(new JValue(new BigInteger(long.MaxValue)))); + Assert.AreEqual(long.MaxValue, (long)(new JValue(new BigInteger(new byte[] { 255, 255, 255, 255, 255, 255, 255, 127 })))); + Assert.AreEqual("9223372036854775807", (string)(new JValue(new BigInteger(long.MaxValue)))); + + intData = (byte[]) (new JValue(new BigInteger(long.MaxValue))); + Assert.AreEqual(new byte[] { 255, 255, 255, 255, 255, 255, 255, 127 }, intData); +#endif } [Test] @@ -394,14 +420,25 @@ namespace Newtonsoft.Json.Tests.Linq ExceptionAssert.Throws("Can not convert Uri to Guid.", () => { var i = (Guid)new JValue(new Uri("http://www.google.com")); }); #if !NET20 - ExceptionAssert.Throws("Can not convert Boolean to DateTimeOffset.", () => { var i = (DateTimeOffset)new JValue(true); }); + ExceptionAssert.Throws("Can not convert Boolean to DateTimeOffset.", () => { var i = (DateTimeOffset)new JValue(true); }); +#endif + ExceptionAssert.Throws("Can not convert Boolean to Uri.", () => { var i = (Uri)new JValue(true); }); + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + ExceptionAssert.Throws("Can not convert Uri to BigInteger.", () => { var i = (BigInteger)new JValue(new Uri("http://www.google.com")); }); + ExceptionAssert.Throws("Can not convert Null to BigInteger.", () => { var i = (BigInteger)new JValue((object)null); }); + ExceptionAssert.Throws("Can not convert Guid to BigInteger.", () => { var i = (BigInteger)new JValue(Guid.NewGuid()); }); #endif - ExceptionAssert.Throws("Can not convert Boolean to Uri.", () => { var i = (Uri)new JValue(true); }); } [Test] public void ToObject() { +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + Assert.AreEqual((BigInteger)1, (new JValue(1).ToObject(typeof(BigInteger)))); + Assert.AreEqual((BigInteger)1, (new JValue(1).ToObject(typeof(BigInteger?)))); + Assert.AreEqual((BigInteger?)null, (new JValue((object)null).ToObject(typeof(BigInteger?)))); +#endif Assert.AreEqual((ushort)1, (new JValue(1).ToObject(typeof(ushort)))); Assert.AreEqual((ushort)1, (new JValue(1).ToObject(typeof(ushort?)))); Assert.AreEqual((uint)1L, (new JValue(1).ToObject(typeof(uint)))); @@ -451,6 +488,11 @@ namespace Newtonsoft.Json.Tests.Linq Assert.IsTrue(JToken.DeepEquals(new JValue((DateTimeOffset?)null), (JValue)(DateTimeOffset?)null)); #endif +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + Assert.IsTrue(JToken.DeepEquals(new JValue(new BigInteger(1)), (JValue)new BigInteger(1))); + Assert.IsTrue(JToken.DeepEquals(new JValue((BigInteger?)null), (JValue)(BigInteger?)null)); +#endif + Assert.IsTrue(JToken.DeepEquals(new JValue(true), (JValue)true)); Assert.IsTrue(JToken.DeepEquals(new JValue(true), (JValue)true)); Assert.IsTrue(JToken.DeepEquals(new JValue(true), (JValue)(bool?)true)); Assert.IsTrue(JToken.DeepEquals(new JValue((bool?)null), (JValue)(bool?)null)); diff --git a/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs index d1a08f81..dd69bf2e 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs @@ -26,6 +26,9 @@ using System; using System.Collections.Generic; using System.IO; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using System.Text; #if !NETFX_CORE using NUnit.Framework; @@ -98,6 +101,13 @@ namespace Newtonsoft.Json.Tests.Linq v.Value = g; Assert.AreEqual(g, v.Value); Assert.AreEqual(JTokenType.Guid, v.Type); + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + BigInteger i = BigInteger.Parse("123456789999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999990"); + v.Value = i; + Assert.AreEqual(i, v.Value); + Assert.AreEqual(JTokenType.Integer, v.Type); +#endif } [Test] @@ -151,8 +161,24 @@ namespace Newtonsoft.Json.Tests.Linq v = new JValue(new Guid("B282ADE7-C520-496C-A448-4084F6803DE5")); Assert.AreEqual("b282ade7-c520-496c-a448-4084f6803de5", v.ToString(null, CultureInfo.InvariantCulture)); + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + v = new JValue(BigInteger.Parse("123456789999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999990")); + Assert.AreEqual("123456789999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999990", v.ToString(null, CultureInfo.InvariantCulture)); +#endif } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + [Test] + public void JValueParse() + { + JValue v = (JValue)JToken.Parse("123456789999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999990"); + + Assert.AreEqual(JTokenType.Integer, v.Type); + Assert.AreEqual(BigInteger.Parse("123456789999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999990"), v.Value); + } +#endif + [Test] public void Last() { @@ -417,6 +443,14 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(Int32.MaxValue, Convert.ToInt32(new JValue(Int32.MaxValue))); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + [Test] + public void ConvertsToInt32_BigInteger() + { + Assert.AreEqual(123, Convert.ToInt32(new JValue(BigInteger.Parse("123")))); + } +#endif + [Test] public void ConvertsToChar() { @@ -483,6 +517,12 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(Decimal.MaxValue, Convert.ToDecimal(new JValue(Decimal.MaxValue))); } + [Test] + public void ConvertsToDecimal_Int64() + { + Assert.AreEqual(123, Convert.ToDecimal(new JValue(123))); + } + [Test] public void ConvertsToString_Decimal() { diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj index 11f25007..d9958b05 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net40.csproj @@ -50,7 +50,7 @@ full false bin\Debug\Net40\ - DEBUG;TRACE + TRACE;DEBUG;NET40 prompt 4 AllRules.ruleset @@ -60,7 +60,7 @@ pdbonly true bin\Release\Net40\ - TRACE + TRACE;NET40 prompt 4 AllRules.ruleset @@ -86,6 +86,7 @@ 3.5 + 3.0 diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj index be6396e9..7066587a 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj @@ -87,6 +87,7 @@ 3.5 + 3.0 diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj index e9a61a2a..4f911eeb 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj @@ -39,6 +39,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index a1522243..b5155b54 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -43,6 +43,8 @@ using System.Security; [assembly: AssemblyTitle("Json.NET Tests .NET 2.0")] #elif NET35 [assembly: AssemblyTitle("Json.NET Tests .NET 3.5")] +#elif NET40 +[assembly: AssemblyTitle("Json.NET Tests .NET 4.0")] #else [assembly: AssemblyTitle("Json.NET Tests")] #endif @@ -73,4 +75,4 @@ using System.Security; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] -[assembly: AssemblyFileVersion("5.0.1.15913")] +[assembly: AssemblyFileVersion("5.0.1.15916")] diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index b8c80a00..d356d739 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -28,6 +28,9 @@ using System; using System.Collections.Concurrent; #endif using System.Collections.Generic; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif #if !SILVERLIGHT && !NET20 && !NETFX_CORE using System.ComponentModel.DataAnnotations; using System.Configuration; @@ -7617,6 +7620,19 @@ Parameter name: value", } #endif +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + public void SerializeBigInteger() + { + BigInteger i = BigInteger.Parse("123456789999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999990"); + + string json = JsonConvert.SerializeObject(new [] {i}, Formatting.Indented); + + Assert.AreEqual(@"[ + 123456789999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999990 +]", json); + } +#endif + #if !(NET40 || NET35 || NET20 || SILVERLIGHT || WINDOWS_PHONE || PORTABLE) [Test] public void DeserializeReadOnlyList() diff --git a/Src/Newtonsoft.Json/Bson/BsonWriter.cs b/Src/Newtonsoft.Json/Bson/BsonWriter.cs index ac10abb8..bda5ea85 100644 --- a/Src/Newtonsoft.Json/Bson/BsonWriter.cs +++ b/Src/Newtonsoft.Json/Bson/BsonWriter.cs @@ -27,6 +27,9 @@ using System; using System.Collections; using System.Collections.Generic; using System.IO; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using System.Text; using Newtonsoft.Json.Utilities; using Newtonsoft.Json.Linq; @@ -459,6 +462,13 @@ namespace Newtonsoft.Json.Bson AddToken(new BsonString(value.ToString(), true)); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + public override void WriteValue(BigInteger value) + { + base.WriteValue(value); + AddToken(new BsonValue(value.ToByteArray(), BsonType.Binary)); + } +#endif #endregion /// diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs index 002b9553..ce718ad4 100644 --- a/Src/Newtonsoft.Json/JsonConvert.cs +++ b/Src/Newtonsoft.Json/JsonConvert.cs @@ -26,6 +26,9 @@ using System; using System.IO; using System.Globalization; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif #if !(NET20 || NET35 || SILVERLIGHT) using System.Threading.Tasks; #endif @@ -421,6 +424,18 @@ namespace Newtonsoft.Json return value.ToString(null, CultureInfo.InvariantCulture); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + /// + /// Converts the to its JSON string representation. + /// + /// The value to convert. + /// A JSON string representation of the . + public static string ToString(BigInteger value) + { + return value.ToString(null, CultureInfo.InvariantCulture); + } +#endif + /// /// Converts the to its JSON string representation. /// @@ -670,6 +685,12 @@ namespace Newtonsoft.Json { return ToString((TimeSpan) value); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + else if (value is BigInteger) + { + return ToString((BigInteger) value); + } +#endif throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } @@ -719,6 +740,10 @@ namespace Newtonsoft.Json return true; if (type == typeof (Guid)) return true; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (type == typeof (BigInteger)) + return true; +#endif return IsJsonPrimitiveTypeCode(ConvertUtils.GetTypeCode(type)); } diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs index 824eab2a..6dc06b32 100644 --- a/Src/Newtonsoft.Json/JsonTextReader.cs +++ b/Src/Newtonsoft.Json/JsonTextReader.cs @@ -26,6 +26,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using System.Text; using System.IO; using System.Xml; @@ -1245,13 +1248,19 @@ namespace Newtonsoft.Json } else { - try + long value; + if (long.TryParse(number, out value)) { - numberValue = Convert.ToInt64(number, CultureInfo.InvariantCulture); + numberValue = value; } - catch (OverflowException ex) + else { - throw JsonReaderException.Create((JsonReader)this, "JSON integer {0} is too large or small for an Int64.".FormatWith(CultureInfo.InvariantCulture, number), ex); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + numberValue = BigInteger.Parse(number, CultureInfo.InvariantCulture); +#else + // todo - validate number was a valid integer to make sure overflow was the reason for failure + throw JsonReaderException.Create((JsonReader)this, "JSON integer {0} is too large or small for an Int64.".FormatWith(CultureInfo.InvariantCulture, number)); +#endif } numberType = JsonToken.Integer; diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs index 3cee32d9..90d841f1 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.cs @@ -26,6 +26,9 @@ using System; using System.Collections.Generic; using System.Globalization; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using System.Text; using System.IO; using System.Xml; @@ -581,6 +584,18 @@ namespace Newtonsoft.Json WriteValueInternal(JsonConvert.ToString(value, _quoteChar), JsonToken.String); } } + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(BigInteger value) + { + InternalWriteValue(JsonToken.Integer); + WriteValueInternal(value.ToString(CultureInfo.InvariantCulture), JsonToken.String); + } +#endif #endregion /// diff --git a/Src/Newtonsoft.Json/JsonValidatingReader.cs b/Src/Newtonsoft.Json/JsonValidatingReader.cs index f1bad867..f43da0af 100644 --- a/Src/Newtonsoft.Json/JsonValidatingReader.cs +++ b/Src/Newtonsoft.Json/JsonValidatingReader.cs @@ -25,6 +25,9 @@ using System; using System.Collections.Generic; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using Newtonsoft.Json.Linq; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Utilities; @@ -711,26 +714,46 @@ namespace Newtonsoft.Json ValidateNotDisallowed(schema); - long value = Convert.ToInt64(_reader.Value, CultureInfo.InvariantCulture); + object value = _reader.Value; if (schema.Maximum != null) { - if (value > schema.Maximum) + if (JValue.Compare(JTokenType.Integer, value, schema.Maximum) > 0) RaiseError("Integer {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema); - if (schema.ExclusiveMaximum && value == schema.Maximum) + if (schema.ExclusiveMaximum && JValue.Compare(JTokenType.Integer, value, schema.Maximum) == 0) RaiseError("Integer {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema); } if (schema.Minimum != null) { - if (value < schema.Minimum) + if (JValue.Compare(JTokenType.Integer, value, schema.Minimum) < 0) RaiseError("Integer {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema); - if (schema.ExclusiveMinimum && value == schema.Minimum) + if (schema.ExclusiveMinimum && JValue.Compare(JTokenType.Integer, value, schema.Minimum) == 0) RaiseError("Integer {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema); } - if (schema.DivisibleBy != null && !IsZero(value % schema.DivisibleBy.Value)) - RaiseError("Integer {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.DivisibleBy), schema); + if (schema.DivisibleBy != null) + { + bool notDivisible; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (value is BigInteger) + { + // not that this will lose any decimal point on DivisibleBy + // so manually raise an error if DivisibleBy is not an integer and value is not zero + BigInteger i = (BigInteger)value; + bool divisibleNonInteger = !Math.Abs(schema.DivisibleBy.Value - Math.Truncate(schema.DivisibleBy.Value)).Equals(0); + if (divisibleNonInteger) + notDivisible = i != 0; + else + notDivisible = i % new BigInteger(schema.DivisibleBy.Value) != 0; + } + else +#endif + notDivisible = !IsZero(Convert.ToInt64(value, CultureInfo.InvariantCulture) % schema.DivisibleBy.Value); + + if (notDivisible) + RaiseError("Integer {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.DivisibleBy), schema); + } } private void ProcessValue() diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index 082f7065..8da942f7 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -26,6 +26,9 @@ using System; using System.Collections.Generic; using System.IO; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using Newtonsoft.Json.Utilities; using System.Globalization; #if NETFX_CORE @@ -1217,6 +1220,17 @@ namespace Newtonsoft.Json InternalWriteValue(JsonToken.String); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + /// + /// Writes a value. + /// + /// The value to write. + public virtual void WriteValue(BigInteger value) + { + InternalWriteValue(JsonToken.Integer); + } +#endif + /// /// Writes a value. /// An error will raised if the value cannot be written as a single JSON token. @@ -1381,6 +1395,13 @@ namespace Newtonsoft.Json WriteValue((TimeSpan)value); return; } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + else if (value is BigInteger) + { + WriteValue((BigInteger)value); + return; + } +#endif throw JsonWriterException.Create(this, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); } diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index 7ec0a88a..a4649492 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -30,6 +30,9 @@ using System.Dynamic; using System.Linq.Expressions; #endif using System.IO; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using System.Text; using Newtonsoft.Json.Utilities; using System.Diagnostics; @@ -64,13 +67,14 @@ namespace Newtonsoft.Json.Linq private static readonly JTokenType[] BooleanTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean }; private static readonly JTokenType[] NumberTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean }; + private static readonly JTokenType[] BigIntegerTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes }; private static readonly JTokenType[] StringTypes = new[] { JTokenType.Date, JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes, JTokenType.Guid, JTokenType.TimeSpan, JTokenType.Uri }; private static readonly JTokenType[] GuidTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Guid }; private static readonly JTokenType[] TimeSpanTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.TimeSpan }; private static readonly JTokenType[] UriTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Uri }; private static readonly JTokenType[] CharTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw }; private static readonly JTokenType[] DateTimeTypes = new[] { JTokenType.Date, JTokenType.String, JTokenType.Comment, JTokenType.Raw }; - private static readonly JTokenType[] BytesTypes = new[] { JTokenType.Bytes, JTokenType.String, JTokenType.Comment, JTokenType.Raw }; + private static readonly JTokenType[] BytesTypes = new[] { JTokenType.Bytes, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Integer }; /// /// Gets a comparer that can compare two tokens for value equality. @@ -451,6 +455,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, BooleanTypes, false)) throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return Convert.ToBoolean((int)(BigInteger)v.Value); +#endif + return Convert.ToBoolean(v.Value, CultureInfo.InvariantCulture); } @@ -488,6 +497,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, BooleanTypes, true)) throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return Convert.ToBoolean((int)(BigInteger)v.Value); +#endif + return (v.Value != null) ? (bool?)Convert.ToBoolean(v.Value, CultureInfo.InvariantCulture) : null; } @@ -502,6 +516,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (long)(BigInteger)v.Value; +#endif + return Convert.ToInt64(v.Value, CultureInfo.InvariantCulture); } @@ -519,6 +538,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, DateTimeTypes, true)) throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !NET20 + if (v.Value is DateTimeOffset) + return ((DateTimeOffset)v.Value).DateTime; +#endif + return (v.Value != null) ? (DateTime?)Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture) : null; } @@ -561,6 +585,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (decimal?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (decimal?)Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture) : null; } @@ -578,6 +607,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (double?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (double?)Convert.ToDouble(v.Value, CultureInfo.InvariantCulture) : null; } @@ -595,6 +629,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, CharTypes, true)) throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (char?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (char?)Convert.ToChar(v.Value, CultureInfo.InvariantCulture) : null; } @@ -609,6 +648,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (int)(BigInteger)v.Value; +#endif + return Convert.ToInt32(v.Value, CultureInfo.InvariantCulture); } @@ -623,6 +667,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (short)(BigInteger)v.Value; +#endif + return Convert.ToInt16(v.Value, CultureInfo.InvariantCulture); } @@ -638,6 +687,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (ushort)(BigInteger)v.Value; +#endif + return Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture); } @@ -653,6 +707,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, CharTypes, false)) throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (char)(BigInteger)v.Value; +#endif + return Convert.ToChar(v.Value, CultureInfo.InvariantCulture); } @@ -667,6 +726,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (byte)(BigInteger)v.Value; +#endif + return Convert.ToByte(v.Value, CultureInfo.InvariantCulture); } @@ -684,6 +748,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (int?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (int?)Convert.ToInt32(v.Value, CultureInfo.InvariantCulture) : null; } @@ -701,6 +770,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (short?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (short?)Convert.ToInt16(v.Value, CultureInfo.InvariantCulture) : null; } @@ -719,6 +793,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (ushort?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (ushort?)Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture) : null; } @@ -736,6 +815,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (byte?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (byte?)Convert.ToByte(v.Value, CultureInfo.InvariantCulture) : null; } @@ -750,6 +834,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, DateTimeTypes, false)) throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !NET20 + if (v.Value is DateTimeOffset) + return ((DateTimeOffset) v.Value).DateTime; +#endif + return Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture); } @@ -767,6 +856,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (long?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (long?)Convert.ToInt64(v.Value, CultureInfo.InvariantCulture) : null; } @@ -784,6 +878,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (float?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (float?)Convert.ToSingle(v.Value, CultureInfo.InvariantCulture) : null; } @@ -798,6 +897,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (decimal)(BigInteger)v.Value; +#endif + return Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture); } @@ -816,6 +920,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (uint?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (uint?)Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture) : null; } @@ -834,6 +943,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (ulong?)(BigInteger)v.Value; +#endif + return (v.Value != null) ? (ulong?)Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture) : null; } @@ -848,6 +962,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (double) (BigInteger) v.Value; +#endif + return Convert.ToDouble(v.Value, CultureInfo.InvariantCulture); } @@ -862,6 +981,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (float)(BigInteger)v.Value; +#endif + return Convert.ToSingle(v.Value, CultureInfo.InvariantCulture); } @@ -883,6 +1007,10 @@ namespace Newtonsoft.Json.Linq return null; if (v.Value is byte[]) return Convert.ToBase64String((byte[]) v.Value); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return ((BigInteger)v.Value).ToString(CultureInfo.InvariantCulture); +#endif return Convert.ToString(v.Value, CultureInfo.InvariantCulture); } @@ -899,6 +1027,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (uint)(BigInteger)v.Value; +#endif + return Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture); } @@ -914,6 +1047,11 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return (ulong)(BigInteger)v.Value; +#endif + return Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture); } @@ -933,7 +1071,15 @@ namespace Newtonsoft.Json.Linq if (v.Value is string) return Convert.FromBase64String(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); - return (byte[])v.Value; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (v.Value is BigInteger) + return ((BigInteger)v.Value).ToByteArray(); +#endif + + if (v.Value is byte[]) + return (byte[])v.Value; + + throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } /// @@ -1023,6 +1169,39 @@ namespace Newtonsoft.Json.Linq return (v.Value is Uri) ? (Uri)v.Value : new Uri(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); } + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator BigInteger(JToken value) + { + JValue v = EnsureValue(value); + if (v == null || !ValidateToken(v, BigIntegerTypes, false)) + throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); + + return ConvertUtils.ToBigInteger(v.Value); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator BigInteger?(JToken value) + { + JValue v = EnsureValue(value); + if (v == null || !ValidateToken(v, BigIntegerTypes, true)) + throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); + + if (v.Value == null) + return null; + + return ConvertUtils.ToBigInteger(v.Value); + } +#endif #endregion #region Cast to operators @@ -1236,6 +1415,18 @@ namespace Newtonsoft.Json.Linq return new JValue(value); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + /// + /// Performs an implicit conversion from to . + /// + /// The value to create a from. + /// The initialized with the specified value. + public static implicit operator JToken(BigInteger? value) + { + return new JValue(value); + } +#endif + /// /// Performs an implicit conversion from to . /// @@ -1298,6 +1489,18 @@ namespace Newtonsoft.Json.Linq return new JValue(value); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + /// + /// Performs an implicit conversion from to . + /// + /// The value to create a from. + /// The initialized with the specified value. + public static implicit operator JToken(BigInteger value) + { + return new JValue(value); + } +#endif + /// /// Performs an implicit conversion from to . /// @@ -1544,6 +1747,15 @@ namespace Newtonsoft.Json.Linq return (TimeSpan) this; } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (objectType == typeof(BigInteger)) + { + if (isNullable) + return (BigInteger?)this; + + return (BigInteger)this; + } +#endif return ToObject(objectType, new JsonSerializer()); } diff --git a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs index 1463de7d..27feebdf 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs @@ -25,6 +25,9 @@ using System; using System.Globalization; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using Newtonsoft.Json.Utilities; namespace Newtonsoft.Json.Linq @@ -428,6 +431,18 @@ namespace Newtonsoft.Json.Linq base.WriteValue(value); AddValue(value, JsonToken.String); } + +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(BigInteger value) + { + base.WriteValue(value); + AddValue(value, JsonToken.Integer); + } +#endif #endregion } } diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs index 00b82ffa..06cd03f9 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.cs @@ -31,6 +31,9 @@ using System.Globalization; using System.Dynamic; using System.Linq.Expressions; #endif +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif namespace Newtonsoft.Json.Linq { @@ -191,7 +194,32 @@ namespace Newtonsoft.Json.Linq get { return false; } } - private static int Compare(JTokenType valueType, object objA, object objB) +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + private static int CompareBigInteger(BigInteger i1, object i2) + { + int result = i1.CompareTo(ConvertUtils.ToBigInteger(i2)); + + if (result != 0) + return result; + + // converting a fractional number to a BigInteger will lose the fraction + // check for fraction if result is two numbers are equal + if (i2 is decimal) + { + decimal d = (decimal) i2; + return (0m).CompareTo(Math.Abs(d - Math.Truncate(d))); + } + else if (i2 is double || i2 is float) + { + double d = Convert.ToDouble(i2, CultureInfo.InvariantCulture); + return (0d).CompareTo(Math.Abs(d - Math.Truncate(d))); + } + + return result; + } +#endif + + internal static int Compare(JTokenType valueType, object objA, object objB) { if (objA == null && objB == null) return 0; @@ -203,6 +231,12 @@ namespace Newtonsoft.Json.Linq switch (valueType) { case JTokenType.Integer: +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (objA is BigInteger) + return CompareBigInteger((BigInteger)objA, objB); + if (objB is BigInteger) + return -CompareBigInteger((BigInteger)objB, objA); +#endif if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture)); else if (objA is float || objB is float || objA is double || objB is double) @@ -210,6 +244,12 @@ namespace Newtonsoft.Json.Linq else return Convert.ToInt64(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToInt64(objB, CultureInfo.InvariantCulture)); case JTokenType.Float: +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (objA is BigInteger) + return CompareBigInteger((BigInteger)objA, objB); + if (objB is BigInteger) + return -CompareBigInteger((BigInteger)objB, objA); +#endif return CompareFloat(objA, objB); case JTokenType.Comment: case JTokenType.String: @@ -319,6 +359,42 @@ namespace Newtonsoft.Json.Linq } } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (objA is BigInteger || objB is BigInteger) + { + if (objA == null || objB == null) + { + result = null; + return true; + } + + // not that this will lose the fraction + // BigInteger doesn't have operators with non-integer types + BigInteger i1 = ConvertUtils.ToBigInteger(objA); + BigInteger i2 = ConvertUtils.ToBigInteger(objB); + + switch (operation) + { + case ExpressionType.Add: + case ExpressionType.AddAssign: + result = i1 + i2; + return true; + case ExpressionType.Subtract: + case ExpressionType.SubtractAssign: + result = i1 - i2; + return true; + case ExpressionType.Multiply: + case ExpressionType.MultiplyAssign: + result = i1 * i2; + return true; + case ExpressionType.Divide: + case ExpressionType.DivideAssign: + result = i1 / i2; + return true; + } + } + else +#endif if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) { if (objA == null || objB == null) @@ -459,6 +535,10 @@ namespace Newtonsoft.Json.Linq return JTokenType.Integer; else if (value is Enum) return JTokenType.Integer; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + else if (value is BigInteger) + return JTokenType.Integer; +#endif else if (value is double || value is float || value is decimal) return JTokenType.Float; else if (value is DateTime) @@ -557,7 +637,12 @@ namespace Newtonsoft.Json.Linq writer.WriteUndefined(); return; case JTokenType.Integer: - writer.WriteValue(Convert.ToInt64(_value, CultureInfo.InvariantCulture)); +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (_value is BigInteger) + writer.WriteValue((BigInteger)_value); + else +#endif + writer.WriteValue(Convert.ToInt64(_value, CultureInfo.InvariantCulture)); return; case JTokenType.Float: if (_value is decimal) @@ -840,87 +925,91 @@ namespace Newtonsoft.Json.Linq if (_value == null) return TypeCode.Empty; +#if !NET20 + if (_value is DateTimeOffset) + return TypeCode.DateTime; +#endif +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (_value is BigInteger) + return TypeCode.Int64; +#endif + return System.Type.GetTypeCode(_value.GetType()); } bool IConvertible.ToBoolean(IFormatProvider provider) { - return Convert.ToBoolean(_value, CultureInfo.InvariantCulture); + return (bool) this; } char IConvertible.ToChar(IFormatProvider provider) { - return Convert.ToChar(_value, CultureInfo.InvariantCulture); + return (char) this; } sbyte IConvertible.ToSByte(IFormatProvider provider) { - return Convert.ToSByte(_value, CultureInfo.InvariantCulture); + return (sbyte) this; } byte IConvertible.ToByte(IFormatProvider provider) { - return Convert.ToByte(_value, CultureInfo.InvariantCulture); + return (byte) this; } short IConvertible.ToInt16(IFormatProvider provider) { - return Convert.ToInt16(_value, CultureInfo.InvariantCulture); + return (short) this; } ushort IConvertible.ToUInt16(IFormatProvider provider) { - return Convert.ToUInt16(_value, CultureInfo.InvariantCulture); + return (ushort) this; } int IConvertible.ToInt32(IFormatProvider provider) { - return Convert.ToInt32(_value, CultureInfo.InvariantCulture); + return (int) this; } uint IConvertible.ToUInt32(IFormatProvider provider) { - return Convert.ToUInt32(_value, CultureInfo.InvariantCulture); + return (uint) this; } long IConvertible.ToInt64(IFormatProvider provider) { - return Convert.ToInt64(_value, CultureInfo.InvariantCulture); + return (long) this; } ulong IConvertible.ToUInt64(IFormatProvider provider) { - return Convert.ToUInt64(_value, CultureInfo.InvariantCulture); + return (ulong) this; } float IConvertible.ToSingle(IFormatProvider provider) { - return Convert.ToSingle(_value, CultureInfo.InvariantCulture); + return (float) this; } double IConvertible.ToDouble(IFormatProvider provider) { - return Convert.ToDouble(_value, CultureInfo.InvariantCulture); + return (double) this; } decimal IConvertible.ToDecimal(IFormatProvider provider) { - return Convert.ToDecimal(_value, CultureInfo.InvariantCulture); + return (decimal) this; } DateTime IConvertible.ToDateTime(IFormatProvider provider) { -#if !NET20 - if (_value is DateTimeOffset) - return ((DateTimeOffset) _value).DateTime; -#endif - - return Convert.ToDateTime(_value, CultureInfo.InvariantCulture); + return (DateTime) this; } object IConvertible.ToType(Type conversionType, IFormatProvider provider) { - return Convert.ChangeType(_value, conversionType, provider); + return ToObject(conversionType); } #endif } diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj index 55db63fc..b4e6e3a1 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj @@ -49,7 +49,7 @@ full false bin\Debug\Net40\ - DEBUG;TRACE + TRACE;DEBUG;NET40;CODE_ANALYSIS prompt 4 bin\Debug\Net40\Newtonsoft.Json.xml @@ -62,7 +62,7 @@ pdbonly true bin\Release\Net40\ - TRACE + TRACE;NET40;CODE_ANALYSIS prompt 4 bin\Release\Net40\Newtonsoft.Json.xml @@ -76,6 +76,7 @@ 3.5 + 3.0 diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 1b7e05a1..c601b7f3 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -46,6 +46,9 @@ using System.Security; #elif NET35 [assembly: AssemblyTitle("Json.NET .NET 3.5")] [assembly: AllowPartiallyTrustedCallers] +#elif NET40 +[assembly: AssemblyTitle("Json.NET .NET 4.0")] +[assembly: AllowPartiallyTrustedCallers] #else [assembly: AssemblyTitle("Json.NET")] [assembly: AllowPartiallyTrustedCallers] @@ -87,6 +90,6 @@ using System.Security; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] -[assembly: AssemblyFileVersion("5.0.1.15913")] +[assembly: AssemblyFileVersion("5.0.1.15916")] [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs index 6f88b2c0..b8c58a93 100644 --- a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs @@ -26,6 +26,9 @@ using System; using System.Globalization; using System.ComponentModel; +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) +using System.Numerics; +#endif using Newtonsoft.Json.Serialization; using System.Reflection; #if NET20 @@ -288,6 +291,34 @@ namespace Newtonsoft.Json.Utilities return o => call(null, o); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + internal static BigInteger ToBigInteger(object value) + { + if (value is BigInteger) + return (BigInteger)value; + if (value is string) + return BigInteger.Parse((string)value, CultureInfo.InvariantCulture); + if (value is float) + return new BigInteger((float)value); + if (value is double) + return new BigInteger((double)value); + if (value is decimal) + return new BigInteger((decimal)value); + if (value is int) + return new BigInteger((int)value); + if (value is long) + return new BigInteger((long)value); + if (value is uint) + return new BigInteger((uint)value); + if (value is ulong) + return new BigInteger((ulong)value); + if (value is byte[]) + return new BigInteger((byte[])value); + + throw new InvalidCastException("Cannot convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); + } +#endif + #region Convert /// /// Converts the value to the specified type. @@ -344,6 +375,27 @@ namespace Newtonsoft.Json.Utilities return ParseTimeSpan((string) initialValue); } +#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) + if (targetType == typeof(BigInteger)) + { + return ToBigInteger(initialValue); + } + if (initialValue is BigInteger) + { + BigInteger i = (BigInteger) initialValue; + if (targetType == typeof(decimal)) + return (decimal) i; + if (targetType == typeof(double)) + return (double) i; + if (targetType == typeof(float)) + return (float) i; + if (targetType == typeof(ulong)) + return (ulong) i; + if (IsConvertible(targetType)) + return System.Convert.ChangeType((long) i, targetType, CultureInfo.InvariantCulture); + } +#endif + #if !(NETFX_CORE || PORTABLE) // see if source or target types have a TypeConverter that converts between the two TypeConverter toConverter = GetConverter(initialType);