diff --git a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs index 85530d78..c1c55aab 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs @@ -234,6 +234,7 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(new DateTime(2000, 12, 20), (DateTime)new JValue(new DateTime(2000, 12, 20))); #if !PocketPC && !NET20 + Assert.AreEqual(new DateTimeOffset(2000, 12, 20, 0, 0, 0, TimeSpan.Zero), (DateTimeOffset)new JValue(new DateTime(2000, 12, 20, 0, 0, 0, DateTimeKind.Utc))); Assert.AreEqual(new DateTimeOffset(2000, 12, 20, 23, 50, 10, TimeSpan.Zero), (DateTimeOffset)new JValue(new DateTimeOffset(2000, 12, 20, 23, 50, 10, TimeSpan.Zero))); Assert.AreEqual(null, (DateTimeOffset?)new JValue((DateTimeOffset?)null)); Assert.AreEqual(null, (DateTimeOffset?)(JValue)null); @@ -281,6 +282,60 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(5f, (float?)(new JValue(5m))); Assert.AreEqual(5, (byte)(new JValue(5))); + Assert.AreEqual("1", (string)(new JValue(1))); + Assert.AreEqual("1", (string)(new JValue(1.0))); + Assert.AreEqual("1.0", (string)(new JValue(1.0m))); + Assert.AreEqual("True", (string)(new JValue(true))); + Assert.AreEqual(null, (string)(new JValue((object)null))); + Assert.AreEqual(null, (string)(JValue)null); + Assert.AreEqual("12/12/2000 12:12:12", (string)(new JValue(new DateTime(2000, 12, 12, 12, 12, 12, DateTimeKind.Utc)))); +#if !NET20 + Assert.AreEqual("12/12/2000 12:12:12 +00:00", (string)(new JValue(new DateTimeOffset(2000, 12, 12, 12, 12, 12, TimeSpan.Zero)))); +#endif + Assert.AreEqual(true, (bool)(new JValue(1))); + Assert.AreEqual(true, (bool)(new JValue(1.0))); + Assert.AreEqual(true, (bool)(new JValue("true"))); + Assert.AreEqual(true, (bool)(new JValue(true))); + Assert.AreEqual(1, (int)(new JValue(1))); + Assert.AreEqual(1, (int)(new JValue(1.0))); + Assert.AreEqual(1, (int)(new JValue("1"))); + Assert.AreEqual(1, (int)(new JValue(true))); + Assert.AreEqual(1m, (decimal)(new JValue(1))); + Assert.AreEqual(1m, (decimal)(new JValue(1.0))); + Assert.AreEqual(1m, (decimal)(new JValue("1"))); + Assert.AreEqual(1m, (decimal)(new JValue(true))); + Assert.AreEqual(TimeSpan.FromMinutes(1), (TimeSpan)(new JValue(TimeSpan.FromMinutes(1)))); + Assert.AreEqual(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC"), (Guid)(new JValue("46EFE013-B56A-4E83-99E4-4DCE7678A5BC"))); + Assert.AreEqual(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC"), (Guid)(new JValue(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC")))); + Assert.AreEqual(new Uri("http://www.google.com"), (Uri)(new JValue("http://www.google.com"))); + Assert.AreEqual(new Uri("http://www.google.com"), (Uri)(new JValue(new Uri("http://www.google.com")))); + Assert.AreEqual(null, (Uri)(new JValue((object)null))); + Assert.AreEqual(Convert.ToBase64String(Encoding.UTF8.GetBytes("hi")), (string)(new JValue(Encoding.UTF8.GetBytes("hi")))); + Assert.AreEqual(Encoding.UTF8.GetBytes("hi"), (byte[])(new JValue(Convert.ToBase64String(Encoding.UTF8.GetBytes("hi"))))); + + Assert.AreEqual(null, (Uri)(JValue)null); + Assert.AreEqual(null, (int?)(JValue)null); + Assert.AreEqual(null, (uint?)(JValue)null); + Assert.AreEqual(null, (Guid?)(JValue)null); + Assert.AreEqual(null, (TimeSpan?)(JValue)null); + Assert.AreEqual(null, (byte[])(JValue)null); + Assert.AreEqual(null, (bool?)(JValue)null); + Assert.AreEqual(null, (char?)(JValue)null); + Assert.AreEqual(null, (DateTime?)(JValue)null); +#if !NET20 + Assert.AreEqual(null, (DateTimeOffset?)(JValue)null); +#endif + Assert.AreEqual(null, (short?)(JValue)null); + Assert.AreEqual(null, (ushort?)(JValue)null); + Assert.AreEqual(null, (byte?)(JValue)null); + Assert.AreEqual(null, (byte?)(JValue)null); + Assert.AreEqual(null, (sbyte?)(JValue)null); + Assert.AreEqual(null, (sbyte?)(JValue)null); + Assert.AreEqual(null, (long?)(JValue)null); + Assert.AreEqual(null, (ulong?)(JValue)null); + Assert.AreEqual(null, (double?)(JValue)null); + Assert.AreEqual(null, (float?)(JValue)null); + byte[] data = new byte[0]; Assert.AreEqual(data, (byte[])(new JValue(data))); @@ -378,6 +433,13 @@ namespace Newtonsoft.Json.Tests.Linq Assert.IsTrue(JToken.DeepEquals(new JValue(emptyData), (JValue)emptyData)); Assert.IsFalse(JToken.DeepEquals(new JValue(emptyData), (JValue)new byte[1])); Assert.IsTrue(JToken.DeepEquals(new JValue(Encoding.UTF8.GetBytes("Hi")), (JValue)Encoding.UTF8.GetBytes("Hi"))); + + Assert.IsTrue(JToken.DeepEquals(new JValue(TimeSpan.FromMinutes(1)), (JValue)TimeSpan.FromMinutes(1))); + Assert.IsTrue(JToken.DeepEquals(new JValue((object)null), (JValue)(TimeSpan?)null)); + Assert.IsTrue(JToken.DeepEquals(new JValue(TimeSpan.FromMinutes(1)), (JValue)(TimeSpan?)TimeSpan.FromMinutes(1))); + Assert.IsTrue(JToken.DeepEquals(new JValue(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC")), (JValue)new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC"))); + Assert.IsTrue(JToken.DeepEquals(new JValue(new Uri("http://www.google.com")), (JValue)new Uri("http://www.google.com"))); + } [Test] diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs index 7505d312..74f0b891 100644 --- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs +++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs @@ -333,6 +333,44 @@ If attributes are not mentioned, default values are used in each case. }, "New"); } + [Test] + public void JTokenToObject() + { + JValue s = new JValue("String!"); + + int interations = 1000000; + + TimeOperation(() => + { + for (int i = 0; i < interations; i++) + { + s.ToObject(typeof (string)); + } + + return ""; + }, "New"); + + TimeOperation(() => + { + for (int i = 0; i < interations; i++) + { + s.ToObject(typeof(string), new JsonSerializer()); + } + + return ""; + }, "Old"); + + TimeOperation(() => + { + for (int i = 0; i < interations; i++) + { + s.Value(); + } + + return ""; + }, "Value"); + } + private void SerializeSize(object value) { // this is extremely slow with 5000 interations diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index da0d87f0..409b51df 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -76,5 +76,5 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.10.15519")] +[assembly: AssemblyFileVersion("4.5.11.15520")] #endif diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index 3301fc49..1579c0fc 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -61,6 +61,13 @@ namespace Newtonsoft.Json.Linq private int? _lineNumber; private int? _linePosition; + 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[] 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[] 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 }; + /// /// Gets a comparer that can compare two tokens for value equality. /// @@ -378,39 +385,9 @@ namespace Newtonsoft.Json.Linq return token.Type.ToString(); } - private static bool IsNullable(JToken o) + private static bool ValidateToken(JToken o, JTokenType[] validTypes, bool nullable) { - return (o.Type == JTokenType.Undefined || o.Type == JTokenType.Null); - } - - private static bool ValidateFloat(JToken o, bool nullable) - { - return (o.Type == JTokenType.Float || o.Type == JTokenType.Integer || (nullable && IsNullable(o))); - } - - private static bool ValidateInteger(JToken o, bool nullable) - { - return (o.Type == JTokenType.Integer || (nullable && IsNullable(o))); - } - - private static bool ValidateDate(JToken o, bool nullable) - { - return (o.Type == JTokenType.Date || (nullable && IsNullable(o))); - } - - private static bool ValidateBoolean(JToken o, bool nullable) - { - return (o.Type == JTokenType.Boolean || (nullable && IsNullable(o))); - } - - private static bool ValidateString(JToken o, bool nullable) - { - return (o.Type == JTokenType.String || o.Type == JTokenType.Comment || o.Type == JTokenType.Raw || (nullable && IsNullable(o))); - } - - private static bool ValidateBytes(JToken o) - { - return (o.Type == JTokenType.Bytes || IsNullable(o)); + return (Array.IndexOf(validTypes, o.Type) != -1) || (nullable && (o.Type == JTokenType.Null || o.Type == JTokenType.Undefined)); } #region Cast from operators @@ -422,7 +399,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator bool(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateBoolean(v, false)) + if (v == null || !ValidateToken(v, BooleanTypes, false)) throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToBoolean(v.Value, CultureInfo.InvariantCulture); @@ -437,10 +414,14 @@ namespace Newtonsoft.Json.Linq public static explicit operator DateTimeOffset(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateDate(v, false)) + if (v == null || !ValidateToken(v, DateTimeTypes, false)) throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - return (DateTimeOffset)v.Value; + if (v.Value is DateTimeOffset) + return (DateTimeOffset)v.Value; + if (v.Value is string) + return DateTimeOffset.Parse((string)v.Value); + return new DateTimeOffset(Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture)); } #endif @@ -455,7 +436,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateBoolean(v, true)) + if (v == null || !ValidateToken(v, BooleanTypes, true)) throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (bool?)Convert.ToBoolean(v.Value, CultureInfo.InvariantCulture) : null; @@ -469,7 +450,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator long(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, false)) + if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToInt64(v.Value, CultureInfo.InvariantCulture); @@ -486,7 +467,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateDate(v, true)) + if (v == null || !ValidateToken(v, DateTimeTypes, true)) throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (DateTime?)Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture) : null; @@ -504,10 +485,16 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateDate(v, true)) + if (v == null || !ValidateToken(v, DateTimeTypes, true)) throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - return (DateTimeOffset?)v.Value; + if (v.Value == null) + return null; + if (v.Value is DateTimeOffset) + return (DateTimeOffset?)v.Value; + if (v.Value is string) + return DateTimeOffset.Parse((string)v.Value); + return new DateTimeOffset(Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture)); } #endif @@ -522,7 +509,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateFloat(v, true)) + if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (decimal?)Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture) : null; @@ -539,7 +526,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateFloat(v, true)) + if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (double?)Convert.ToDouble(v.Value, CultureInfo.InvariantCulture) : null; @@ -556,7 +543,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateString(v, true)) + if (v == null || !ValidateToken(v, CharTypes, true)) throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (char?)Convert.ToChar(v.Value, CultureInfo.InvariantCulture) : null; @@ -570,7 +557,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator int(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, false)) + if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToInt32(v.Value, CultureInfo.InvariantCulture); @@ -584,7 +571,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator short(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, false)) + if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToInt16(v.Value, CultureInfo.InvariantCulture); @@ -599,7 +586,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator ushort(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, false)) + if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture); @@ -614,7 +601,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator char(JToken value) { JValue v = EnsureValue(value); - if (v == null || (!ValidateInteger(v, false) && !ValidateString(v, false))) + if (v == null || !ValidateToken(v, CharTypes, false)) throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToChar(v.Value, CultureInfo.InvariantCulture); @@ -628,7 +615,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator byte(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, false)) + if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToByte(v.Value, CultureInfo.InvariantCulture); @@ -645,7 +632,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, true)) + if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (int?)Convert.ToInt32(v.Value, CultureInfo.InvariantCulture) : null; @@ -662,7 +649,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, true)) + if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (short?)Convert.ToInt16(v.Value, CultureInfo.InvariantCulture) : null; @@ -680,7 +667,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, true)) + if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (ushort?)Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture) : null; @@ -697,7 +684,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, true)) + if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (byte?)Convert.ToByte(v.Value, CultureInfo.InvariantCulture) : null; @@ -711,7 +698,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator DateTime(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateDate(v, false)) + if (v == null || !ValidateToken(v, DateTimeTypes, false)) throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture); @@ -728,7 +715,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, true)) + if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (long?)Convert.ToInt64(v.Value, CultureInfo.InvariantCulture) : null; @@ -745,7 +732,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateFloat(v, true)) + if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (float?)Convert.ToSingle(v.Value, CultureInfo.InvariantCulture) : null; @@ -759,7 +746,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator decimal(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateFloat(v, false)) + if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture); @@ -777,7 +764,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, true)) + if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (uint?)Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture) : null; @@ -795,7 +782,7 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, true)) + if (v == null || !ValidateToken(v, NumberTypes, true)) throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value != null) ? (ulong?)Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture) : null; @@ -809,7 +796,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator double(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateFloat(v, false)) + if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToDouble(v.Value, CultureInfo.InvariantCulture); @@ -823,7 +810,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator float(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateFloat(v, false)) + if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToSingle(v.Value, CultureInfo.InvariantCulture); @@ -840,10 +827,15 @@ namespace Newtonsoft.Json.Linq return null; JValue v = EnsureValue(value); - if (v == null || !ValidateString(v, true)) + if (v == null || !ValidateToken(v, StringTypes, true)) throw new ArgumentException("Can not convert {0} to String.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - return (v.Value != null) ? Convert.ToString(v.Value, CultureInfo.InvariantCulture) : null; + if (v.Value == null) + return null; + if (v.Value is byte[]) + return Convert.ToBase64String((byte[]) v.Value); + + return Convert.ToString(v.Value, CultureInfo.InvariantCulture); } /// @@ -855,7 +847,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator uint(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, false)) + if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture); @@ -870,7 +862,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator ulong(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateInteger(v, false)) + if (v == null || !ValidateToken(v, NumberTypes, false)) throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture); @@ -883,10 +875,15 @@ namespace Newtonsoft.Json.Linq /// The result of the conversion. public static explicit operator byte[](JToken value) { + if (value == null) + return null; + JValue v = EnsureValue(value); - if (v == null || !ValidateBytes(v)) + if (v == null || !ValidateToken(v, BytesTypes, false)) throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); + if (v.Value is string) + return Convert.FromBase64String(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); return (byte[])v.Value; } @@ -898,10 +895,10 @@ namespace Newtonsoft.Json.Linq public static explicit operator Guid(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateString(v, false)) + if (v == null || !ValidateToken(v, StringTypes, false)) throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - return (v.Value is Guid) ? (Guid)v.Value : new Guid((string)v.Value); + return (v.Value is Guid) ? (Guid)v.Value : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); } /// @@ -911,8 +908,11 @@ namespace Newtonsoft.Json.Linq /// The result of the conversion. public static explicit operator Guid?(JToken value) { + if (value == null) + return null; + JValue v = EnsureValue(value); - if (v == null || !ValidateString(v, true)) + if (v == null || !ValidateToken(v, StringTypes, true)) throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); if (v.Value == null) @@ -929,7 +929,7 @@ namespace Newtonsoft.Json.Linq public static explicit operator TimeSpan(JToken value) { JValue v = EnsureValue(value); - if (v == null || !ValidateString(v, false)) + if (v == null || !ValidateToken(v, StringTypes, false)) throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); return (v.Value is TimeSpan) ? (TimeSpan)v.Value : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); @@ -942,8 +942,11 @@ namespace Newtonsoft.Json.Linq /// The result of the conversion. public static explicit operator TimeSpan?(JToken value) { + if (value == null) + return null; + JValue v = EnsureValue(value); - if (v == null || !ValidateString(v, true)) + if (v == null || !ValidateToken(v, StringTypes, true)) throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); if (v.Value == null) @@ -959,8 +962,11 @@ namespace Newtonsoft.Json.Linq /// The result of the conversion. public static explicit operator Uri(JToken value) { + if (value == null) + return null; + JValue v = EnsureValue(value); - if (v == null || !ValidateString(v, true)) + if (v == null || !ValidateToken(v, StringTypes, true)) throw new ArgumentException("Can not convert {0} to Uri.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); if (v.Value == null) @@ -1242,6 +1248,56 @@ namespace Newtonsoft.Json.Linq { return new JValue(value); } + + /// + /// Performs an implicit conversion from to . + /// + /// The value to create a from. + /// The initialized with the specified value. + public static implicit operator JToken(Uri value) + { + return new JValue(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value to create a from. + /// The initialized with the specified value. + public static implicit operator JToken(TimeSpan value) + { + return new JValue(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value to create a from. + /// The initialized with the specified value. + public static implicit operator JToken(TimeSpan? value) + { + return new JValue(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value to create a from. + /// The initialized with the specified value. + public static implicit operator JToken(Guid value) + { + return new JValue(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value to create a from. + /// The initialized with the specified value. + public static implicit operator JToken(Guid? value) + { + return new JValue(value); + } #endregion IEnumerator IEnumerable.GetEnumerator() diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs index d9218b05..49a52e30 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.cs @@ -135,7 +135,7 @@ namespace Newtonsoft.Json.Linq /// /// The value. public JValue(Guid value) - : this(value, JTokenType.String) + : this(value, JTokenType.Guid) { } @@ -144,7 +144,7 @@ namespace Newtonsoft.Json.Linq /// /// The value. public JValue(Uri value) - : this(value, JTokenType.String) + : this(value, JTokenType.Uri) { } @@ -153,7 +153,7 @@ namespace Newtonsoft.Json.Linq /// /// The value. public JValue(TimeSpan value) - : this(value, JTokenType.String) + : this(value, JTokenType.TimeSpan) { } diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 0b296de5..14c65067 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -90,7 +90,7 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.10.15519")] +[assembly: AssemblyFileVersion("4.5.11.15520")] #endif [assembly: CLSCompliant(true)]