diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs index 7548052d..18e701cd 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs @@ -31,6 +31,7 @@ using System.Text; using NUnit.Framework; using Newtonsoft.Json.Bson; using System.IO; +using Newtonsoft.Json.Tests.Serialization; using Newtonsoft.Json.Utilities; using Newtonsoft.Json.Linq; @@ -1164,5 +1165,54 @@ namespace Newtonsoft.Json.Tests.Bson Assert.IsTrue(reader.Read()); Assert.AreEqual(JsonToken.EndObject, reader.TokenType); } + + public void UriGuidTimeSpanTestClassEmptyTest() + { + UriGuidTimeSpanTestClass c1 = new UriGuidTimeSpanTestClass(); + + var memoryStream = new MemoryStream(); + var bsonWriter = new BsonWriter(memoryStream); + JsonSerializer serializer = new JsonSerializer(); + serializer.Serialize(bsonWriter, c1); + bsonWriter.Flush(); + memoryStream.Position = 0; + + var bsonReader = new BsonReader(memoryStream); + + UriGuidTimeSpanTestClass c2 = serializer.Deserialize(bsonReader); + Assert.AreEqual(c1.Guid, c2.Guid); + Assert.AreEqual(c1.NullableGuid, c2.NullableGuid); + Assert.AreEqual(c1.TimeSpan, c2.TimeSpan); + Assert.AreEqual(c1.NullableTimeSpan, c2.NullableTimeSpan); + Assert.AreEqual(c1.Uri, c2.Uri); + } + + public void UriGuidTimeSpanTestClassValuesTest() + { + UriGuidTimeSpanTestClass c1 = new UriGuidTimeSpanTestClass + { + Guid = new Guid("1924129C-F7E0-40F3-9607-9939C531395A"), + NullableGuid = new Guid("9E9F3ADF-E017-4F72-91E0-617EBE85967D"), + TimeSpan = TimeSpan.FromDays(1), + NullableTimeSpan = TimeSpan.FromHours(1), + Uri = new Uri("http://testuri.com") + }; + + var memoryStream = new MemoryStream(); + var bsonWriter = new BsonWriter(memoryStream); + JsonSerializer serializer = new JsonSerializer(); + serializer.Serialize(bsonWriter, c1); + bsonWriter.Flush(); + memoryStream.Position = 0; + + var bsonReader = new BsonReader(memoryStream); + + UriGuidTimeSpanTestClass c2 = serializer.Deserialize(bsonReader); + Assert.AreEqual(c1.Guid, c2.Guid); + Assert.AreEqual(c1.NullableGuid, c2.NullableGuid); + Assert.AreEqual(c1.TimeSpan, c2.TimeSpan); + Assert.AreEqual(c1.NullableTimeSpan, c2.NullableTimeSpan); + Assert.AreEqual(c1.Uri, c2.Uri); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs b/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs index 12c6e239..83b3f8f6 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs @@ -118,7 +118,10 @@ namespace Newtonsoft.Json.Tests.Linq new JProperty("DateTime", new JValue(new DateTime(2000, 12, 29, 23, 51, 10, DateTimeKind.Utc))), new JProperty("Boolean", new JValue(true)), new JProperty("String", new JValue("A string lol!")), - new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!"))) + new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!"))), + 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)) ); dynamic d = o; @@ -166,6 +169,27 @@ namespace Newtonsoft.Json.Tests.Linq Assert.IsTrue(d.Bytes == d.Bytes); Assert.IsTrue(d.Bytes == Encoding.UTF8.GetBytes("A string lol!")); Assert.IsTrue(d.Bytes == new JValue(Encoding.UTF8.GetBytes("A string lol!"))); + + Assert.IsTrue(d.Uri == d.Uri); + Assert.IsTrue(d.Uri == new Uri("http://json.codeplex.com/")); + Assert.IsTrue(d.Uri > new Uri("http://abc.org/")); + Assert.IsTrue(d.Uri >= new Uri("http://abc.com/")); + Assert.IsTrue(d.Uri > null); + Assert.IsTrue(d.Uri >= null); + + Assert.IsTrue(d.Guid == d.Guid); + Assert.IsTrue(d.Guid == new Guid("EA27FE1D-0D80-44F2-BF34-4654156FA7AF")); + Assert.IsTrue(d.Guid > new Guid("AAAAAAAA-0D80-44F2-BF34-4654156FA7AF")); + Assert.IsTrue(d.Guid >= new Guid("AAAAAAAA-0D80-44F2-BF34-4654156FA7AF")); + Assert.IsTrue(d.Guid > null); + Assert.IsTrue(d.Guid >= null); + + Assert.IsTrue(d.TimeSpan == d.TimeSpan); + Assert.IsTrue(d.TimeSpan == TimeSpan.FromDays(1)); + Assert.IsTrue(d.TimeSpan > TimeSpan.FromHours(1)); + Assert.IsTrue(d.TimeSpan >= TimeSpan.FromHours(1)); + Assert.IsTrue(d.TimeSpan > null); + Assert.IsTrue(d.TimeSpan >= null); } [Test] @@ -179,7 +203,10 @@ namespace Newtonsoft.Json.Tests.Linq new JProperty("DateTime", new JValue(new DateTime(2000, 12, 29, 23, 51, 10, DateTimeKind.Utc))), new JProperty("Boolean", new JValue(true)), new JProperty("String", new JValue("A string lol!")), - new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!"))) + new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!"))), + 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)) ); dynamic d = o; @@ -454,7 +481,10 @@ namespace Newtonsoft.Json.Tests.Linq new JProperty("DateTime", new JValue(new DateTime(2000, 12, 29, 23, 51, 10, DateTimeKind.Utc))), new JProperty("Boolean", new JValue(true)), new JProperty("String", new JValue("A string lol!")), - new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!"))) + new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!"))), + 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)) ); dynamic d = o; @@ -466,6 +496,9 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual("True", d.Boolean.ToString()); Assert.AreEqual("A string lol!", d.String.ToString()); Assert.AreEqual("System.Byte[]", d.Bytes.ToString()); + 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()); } [Test] @@ -539,6 +572,14 @@ namespace Newtonsoft.Json.Tests.Linq AssertValueConverted(ushort.MinValue); AssertValueConverted(ushort.MinValue); AssertValueConverted(null); + AssertValueConverted(TimeSpan.FromDays(1)); + AssertValueConverted(TimeSpan.FromDays(1)); + AssertValueConverted(null); + AssertValueConverted(new Guid("60304274-CD13-4060-B38C-057C8557AB54")); + AssertValueConverted(new Guid("60304274-CD13-4060-B38C-057C8557AB54")); + AssertValueConverted(null); + AssertValueConverted(new Uri("http://json.codeplex.com/")); + AssertValueConverted(null); } 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 0a14d86e..731e3443 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs @@ -1591,5 +1591,32 @@ Parameter name: arrayIndex")] Assert.AreEqual(false, prop4.ShouldSerializeValue(o)); } #endif + + [Test] + public void FromObjectTimeSpan() + { + JValue v = (JValue)JToken.FromObject(TimeSpan.FromDays(1)); + Assert.AreEqual(v.Value, TimeSpan.FromDays(1)); + + Assert.AreEqual("1.00:00:00", v.ToString()); + } + + [Test] + public void FromObjectUri() + { + JValue v = (JValue)JToken.FromObject(new Uri("http://www.stuff.co.nz")); + Assert.AreEqual(v.Value, new Uri("http://www.stuff.co.nz")); + + Assert.AreEqual("http://www.stuff.co.nz/", v.ToString()); + } + + [Test] + public void FromObjectGuid() + { + JValue v = (JValue)JToken.FromObject(new Guid("9065ACF3-C820-467D-BE50-8D4664BEAF35")); + Assert.AreEqual(v.Value, new Guid("9065ACF3-C820-467D-BE50-8D4664BEAF35")); + + Assert.AreEqual("9065acf3-c820-467d-be50-8d4664beaf35", v.ToString()); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs index 16ebf467..94673a23 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs @@ -71,6 +71,19 @@ namespace Newtonsoft.Json.Tests.Linq v.Value = StringComparison.OrdinalIgnoreCase; Assert.AreEqual(StringComparison.OrdinalIgnoreCase, v.Value); Assert.AreEqual(JTokenType.Integer, v.Type); + + v.Value = new Uri("http://json.codeplex.com/"); + Assert.AreEqual(new Uri("http://json.codeplex.com/"), v.Value); + Assert.AreEqual(JTokenType.Uri, v.Type); + + v.Value = TimeSpan.FromDays(1); + Assert.AreEqual(TimeSpan.FromDays(1), v.Value); + Assert.AreEqual(JTokenType.TimeSpan, v.Type); + + Guid g = Guid.NewGuid(); + v.Value = g; + Assert.AreEqual(g, v.Value); + Assert.AreEqual(JTokenType.Guid, v.Type); } [Test] @@ -115,6 +128,15 @@ namespace Newtonsoft.Json.Tests.Linq v = new JValue(new DateTime(2000, 12, 12, 20, 59, 59, DateTimeKind.Utc), JTokenType.Date); Assert.AreEqual("12/12/2000 20:59:59", v.ToString(null, CultureInfo.InvariantCulture)); + + v = new JValue(new Uri("http://json.codeplex.com/")); + Assert.AreEqual("http://json.codeplex.com/", v.ToString(null, CultureInfo.InvariantCulture)); + + v = new JValue(TimeSpan.FromDays(1)); + Assert.AreEqual("1.00:00:00", v.ToString(null, CultureInfo.InvariantCulture)); + + v = new JValue(new Guid("B282ADE7-C520-496C-A448-4084F6803DE5")); + Assert.AreEqual("b282ade7-c520-496c-a448-4084f6803de5", v.ToString(null, CultureInfo.InvariantCulture)); } [Test] diff --git a/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs b/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs index 73fae2b4..56ea70ff 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs @@ -33,6 +33,7 @@ using Newtonsoft.Json.Linq; using System.Xml; using System.IO; using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Tests.Serialization; using Newtonsoft.Json.Tests.TestObjects; namespace Newtonsoft.Json.Tests.Linq @@ -782,5 +783,54 @@ keyword such as type of business."" }, o.Children()["item"].Children()["title"].Values().ToArray()); } + + public void UriGuidTimeSpanTestClassEmptyTest() + { + UriGuidTimeSpanTestClass c1 = new UriGuidTimeSpanTestClass(); + JObject o = JObject.FromObject(c1); + + Assert.AreEqual(@"{ + ""Guid"": ""00000000-0000-0000-0000-000000000000"", + ""NullableGuid"": null, + ""TimeSpan"": ""00:00:00"", + ""NullableTimeSpan"": null, + ""Uri"": null +}", o.ToString()); + + UriGuidTimeSpanTestClass c2 = o.ToObject(); + Assert.AreEqual(c1.Guid, c2.Guid); + Assert.AreEqual(c1.NullableGuid, c2.NullableGuid); + Assert.AreEqual(c1.TimeSpan, c2.TimeSpan); + Assert.AreEqual(c1.NullableTimeSpan, c2.NullableTimeSpan); + Assert.AreEqual(c1.Uri, c2.Uri); + } + + public void UriGuidTimeSpanTestClassValuesTest() + { + UriGuidTimeSpanTestClass c1 = new UriGuidTimeSpanTestClass + { + Guid = new Guid("1924129C-F7E0-40F3-9607-9939C531395A"), + NullableGuid = new Guid("9E9F3ADF-E017-4F72-91E0-617EBE85967D"), + TimeSpan = TimeSpan.FromDays(1), + NullableTimeSpan = TimeSpan.FromHours(1), + Uri = new Uri("http://testuri.com") + }; + JObject o = JObject.FromObject(c1); + + Assert.AreEqual(@"{ + ""Guid"": ""1924129c-f7e0-40f3-9607-9939c531395a"", + ""NullableGuid"": ""9e9f3adf-e017-4f72-91e0-617ebe85967d"", + ""TimeSpan"": ""1.00:00:00"", + ""NullableTimeSpan"": ""01:00:00"", + ""Uri"": ""http://testuri.com/"" +}", o.ToString()); + + UriGuidTimeSpanTestClass c2 = o.ToObject(); + Assert.AreEqual(c1.Guid, c2.Guid); + Assert.AreEqual(c1.NullableGuid, c2.NullableGuid); + Assert.AreEqual(c1.TimeSpan, c2.TimeSpan); + Assert.AreEqual(c1.NullableTimeSpan, c2.NullableTimeSpan); + Assert.AreEqual(c1.Uri, c2.Uri); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 3bafc02a..c446773b 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -4795,5 +4795,63 @@ keyword such as type of business."" IList list = JsonConvert.DeserializeObject("['1', 'two', 'III']"); Assert.AreEqual(3, list.Count); } + + public void UriGuidTimeSpanTestClassEmptyTest() + { + UriGuidTimeSpanTestClass c1 = new UriGuidTimeSpanTestClass(); + string json = JsonConvert.SerializeObject(c1, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Guid"": ""00000000-0000-0000-0000-000000000000"", + ""NullableGuid"": null, + ""TimeSpan"": ""00:00:00"", + ""NullableTimeSpan"": null, + ""Uri"": null +}", json); + + UriGuidTimeSpanTestClass c2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual(c1.Guid, c2.Guid); + Assert.AreEqual(c1.NullableGuid, c2.NullableGuid); + Assert.AreEqual(c1.TimeSpan, c2.TimeSpan); + Assert.AreEqual(c1.NullableTimeSpan, c2.NullableTimeSpan); + Assert.AreEqual(c1.Uri, c2.Uri); + } + + public void UriGuidTimeSpanTestClassValuesTest() + { + UriGuidTimeSpanTestClass c1 = new UriGuidTimeSpanTestClass + { + Guid = new Guid("1924129C-F7E0-40F3-9607-9939C531395A"), + NullableGuid = new Guid("9E9F3ADF-E017-4F72-91E0-617EBE85967D"), + TimeSpan = TimeSpan.FromDays(1), + NullableTimeSpan = TimeSpan.FromHours(1), + Uri = new Uri("http://testuri.com") + }; + string json = JsonConvert.SerializeObject(c1, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Guid"": ""1924129c-f7e0-40f3-9607-9939c531395a"", + ""NullableGuid"": ""9e9f3adf-e017-4f72-91e0-617ebe85967d"", + ""TimeSpan"": ""1.00:00:00"", + ""NullableTimeSpan"": ""01:00:00"", + ""Uri"": ""http://testuri.com/"" +}", json); + + UriGuidTimeSpanTestClass c2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual(c1.Guid, c2.Guid); + Assert.AreEqual(c1.NullableGuid, c2.NullableGuid); + Assert.AreEqual(c1.TimeSpan, c2.TimeSpan); + Assert.AreEqual(c1.NullableTimeSpan, c2.NullableTimeSpan); + Assert.AreEqual(c1.Uri, c2.Uri); + } + } + + public class UriGuidTimeSpanTestClass + { + public Guid Guid { get; set; } + public Guid? NullableGuid { get; set; } + public TimeSpan TimeSpan { get; set; } + public TimeSpan? NullableTimeSpan { get; set; } + public Uri Uri { get; set; } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Bson/BsonWriter.cs b/Src/Newtonsoft.Json/Bson/BsonWriter.cs index 4f7c4cbe..3d2d6ebc 100644 --- a/Src/Newtonsoft.Json/Bson/BsonWriter.cs +++ b/Src/Newtonsoft.Json/Bson/BsonWriter.cs @@ -410,6 +410,36 @@ namespace Newtonsoft.Json.Bson base.WriteValue(value); AddValue(value, BsonType.Binary); } + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(Guid value) + { + base.WriteValue(value); + AddToken(new BsonString(value.ToString(), true)); + } + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(TimeSpan value) + { + base.WriteValue(value); + AddToken(new BsonString(value.ToString(), true)); + } + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(Uri value) + { + base.WriteValue(value); + AddToken(new BsonString(value.ToString(), true)); + } #endregion /// diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs index f3a09788..86d20d54 100644 --- a/Src/Newtonsoft.Json/JsonConvert.cs +++ b/Src/Newtonsoft.Json/JsonConvert.cs @@ -375,6 +375,26 @@ namespace Newtonsoft.Json return '"' + value.ToString("D", CultureInfo.InvariantCulture) + '"'; } + /// + /// Converts the to its JSON string representation. + /// + /// The value to convert. + /// A JSON string representation of the . + public static string ToString(TimeSpan value) + { + return '"' + value.ToString() + '"'; + } + + /// + /// Converts the to its JSON string representation. + /// + /// The value to convert. + /// A JSON string representation of the . + public static string ToString(Uri value) + { + return '"' + value.ToString() + '"'; + } + /// /// Converts the to its JSON string representation. /// @@ -452,6 +472,18 @@ namespace Newtonsoft.Json return ToString((DateTimeOffset)value); } #endif + else if (value is Guid) + { + return ToString((Guid) value); + } + else if (value is Uri) + { + return ToString((Uri) value); + } + else if (value is TimeSpan) + { + return ToString((TimeSpan) value); + } throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } @@ -493,6 +525,12 @@ namespace Newtonsoft.Json #endif if (type == typeof(byte[])) return true; + if (type == typeof(Uri)) + return true; + if (type == typeof(TimeSpan)) + return true; + if (type == typeof(Guid)) + return true; return IsJsonPrimitiveTypeCode(Type.GetTypeCode(type)); } @@ -511,9 +549,14 @@ namespace Newtonsoft.Json if (value is DateTimeOffset) return true; #endif - if (value is byte[]) return true; + if (value is Uri) + return true; + if (value is TimeSpan) + return true; + if (value is Guid) + return true; return false; } diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs index 02aa35a9..71cce015 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.cs @@ -461,6 +461,36 @@ namespace Newtonsoft.Json WriteValueInternal(JsonConvert.ToString(value), JsonToken.Date); } #endif + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(Guid value) + { + base.WriteValue(value); + WriteValueInternal(JsonConvert.ToString(value), JsonToken.String); + } + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(TimeSpan value) + { + base.WriteValue(value); + WriteValueInternal(JsonConvert.ToString(value), JsonToken.Date); + } + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(Uri value) + { + base.WriteValue(value); + WriteValueInternal(JsonConvert.ToString(value), JsonToken.Date); + } #endregion /// diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index 9a5b8c1e..00b5c7db 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -814,6 +814,24 @@ namespace Newtonsoft.Json } #endif + /// + /// Writes a value. + /// + /// The value to write. + public virtual void WriteValue(Guid value) + { + AutoComplete(JsonToken.String); + } + + /// + /// Writes a value. + /// + /// The value to write. + public virtual void WriteValue(TimeSpan value) + { + AutoComplete(JsonToken.String); + } + /// /// Writes a value. /// @@ -1000,6 +1018,30 @@ namespace Newtonsoft.Json } #endif + /// + /// Writes a value. + /// + /// The value to write. + public virtual void WriteValue(Guid? value) + { + if (value == null) + WriteNull(); + else + WriteValue(value.Value); + } + + /// + /// Writes a value. + /// + /// The value to write. + public virtual void WriteValue(TimeSpan? value) + { + if (value == null) + WriteNull(); + else + WriteValue(value.Value); + } + /// /// Writes a value. /// @@ -1012,6 +1054,18 @@ namespace Newtonsoft.Json AutoComplete(JsonToken.Bytes); } + /// + /// Writes a value. + /// + /// The value to write. + public virtual void WriteValue(Uri value) + { + if (value == null) + WriteNull(); + else + AutoComplete(JsonToken.String); + } + /// /// Writes a value. /// An error will raised if the value cannot be written as a single JSON token. @@ -1092,6 +1146,21 @@ namespace Newtonsoft.Json WriteValue((byte[])value); return; } + else if (value is Guid) + { + WriteValue((Guid)value); + return; + } + else if (value is Uri) + { + WriteValue((Uri)value); + return; + } + else if (value is TimeSpan) + { + WriteValue((TimeSpan)value); + return; + } throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index a024f208..600dbe31 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -1157,6 +1157,30 @@ namespace Newtonsoft.Json.Linq return FromObjectInternal(o, jsonSerializer); } + /// + /// Creates the specified .NET type from the . + /// + /// The new object created from the JSON value. + public T ToObject() + { + return ToObject(new JsonSerializer()); + } + + /// + /// Creates the specified .NET type from the using the specified . + /// + /// The that will be used when creating the object. + /// The new object created from the JSON value. + public T ToObject(JsonSerializer jsonSerializer) + { + ValidationUtils.ArgumentNotNull(jsonSerializer, "jsonSerializer"); + + using (JTokenReader jsonReader = new JTokenReader(this)) + { + return jsonSerializer.Deserialize(jsonReader); + } + } + /// /// Creates a from a . /// diff --git a/Src/Newtonsoft.Json/Linq/JTokenReader.cs b/Src/Newtonsoft.Json/Linq/JTokenReader.cs index f70f6f11..b88495b5 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenReader.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenReader.cs @@ -242,11 +242,25 @@ namespace Newtonsoft.Json.Linq case JTokenType.Bytes: SetToken(JsonToken.Bytes, ((JValue)token).Value); break; + case JTokenType.Guid: + SetToken(JsonToken.String, SafeToString(((JValue)token).Value)); + break; + case JTokenType.Uri: + SetToken(JsonToken.String, SafeToString(((JValue)token).Value)); + break; + case JTokenType.TimeSpan: + SetToken(JsonToken.String, SafeToString(((JValue)token).Value)); + break; default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", token.Type, "Unexpected JTokenType."); } } + private string SafeToString(object value) + { + return (value != null) ? value.ToString() : null; + } + bool IJsonLineInfo.HasLineInfo() { if (CurrentState == State.Start) diff --git a/Src/Newtonsoft.Json/Linq/JTokenType.cs b/Src/Newtonsoft.Json/Linq/JTokenType.cs index dafb7e12..18e0500a 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenType.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenType.cs @@ -89,6 +89,18 @@ namespace Newtonsoft.Json.Linq /// /// A collection of bytes value. /// - Bytes + Bytes, + /// + /// A Guid value. + /// + Guid, + /// + /// A Uri value. + /// + Uri, + /// + /// A TimeSpan value. + /// + TimeSpan } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs index ecb208d8..2aa233d1 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs @@ -368,6 +368,36 @@ namespace Newtonsoft.Json.Linq base.WriteValue(value); AddValue(value, JsonToken.Bytes); } + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(TimeSpan value) + { + base.WriteValue(value); + AddValue(value, JsonToken.String); + } + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(Guid value) + { + base.WriteValue(value); + AddValue(value, JsonToken.String); + } + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(Uri value) + { + base.WriteValue(value); + AddValue(value, JsonToken.String); + } #endregion } } diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs index 927e36b4..2054e84f 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.cs @@ -115,6 +115,33 @@ namespace Newtonsoft.Json.Linq { } + /// + /// Initializes a new instance of the class with the given value. + /// + /// The value. + public JValue(Guid value) + : this(value, JTokenType.String) + { + } + + /// + /// Initializes a new instance of the class with the given value. + /// + /// The value. + public JValue(Uri value) + : this(value, JTokenType.String) + { + } + + /// + /// Initializes a new instance of the class with the given value. + /// + /// The value. + public JValue(TimeSpan value) + : this(value, JTokenType.String) + { + } + /// /// Initializes a new instance of the class with the given value. /// @@ -192,15 +219,15 @@ namespace Newtonsoft.Json.Linq if (!(objB is DateTimeOffset)) throw new ArgumentException("Object must be of type DateTimeOffset."); - DateTimeOffset date1 = (DateTimeOffset)objA; - DateTimeOffset date2 = (DateTimeOffset)objB; + DateTimeOffset date1 = (DateTimeOffset) objA; + DateTimeOffset date2 = (DateTimeOffset) objB; return date1.CompareTo(date2); } #endif case JTokenType.Bytes: if (!(objB is byte[])) - throw new ArgumentException("Object must be of type byte[]."); + throw new ArgumentException("Object must be of type byte[]."); byte[] bytes1 = objA as byte[]; byte[] bytes2 = objB as byte[]; @@ -210,6 +237,30 @@ namespace Newtonsoft.Json.Linq return 1; return MiscellaneousUtils.ByteArrayCompare(bytes1, bytes2); + case JTokenType.Guid: + if (!(objB is Guid)) + throw new ArgumentException("Object must be of type Guid."); + + Guid guid1 = (Guid) objA; + Guid guid2 = (Guid) objB; + + return guid1.CompareTo(guid2); + case JTokenType.Uri: + if (!(objB is Uri)) + throw new ArgumentException("Object must be of type Uri."); + + Uri uri1 = (Uri)objA; + Uri uri2 = (Uri)objB; + + return Comparer.Default.Compare(uri1.ToString(), uri2.ToString()); + case JTokenType.TimeSpan: + if (!(objB is TimeSpan)) + throw new ArgumentException("Object must be of type TimeSpan."); + + TimeSpan ts1 = (TimeSpan)objA; + TimeSpan ts2 = (TimeSpan)objB; + + return ts1.CompareTo(ts2); default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("valueType", valueType, "Unexpected value type: {0}".FormatWith(CultureInfo.InvariantCulture, valueType)); } @@ -389,6 +440,12 @@ namespace Newtonsoft.Json.Linq return JTokenType.Bytes; else if (value is bool) return JTokenType.Boolean; + else if (value is Guid) + return JTokenType.Guid; + else if (value is Uri) + return JTokenType.Uri; + else if (value is TimeSpan) + return JTokenType.TimeSpan; throw new ArgumentException("Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } @@ -492,6 +549,11 @@ namespace Newtonsoft.Json.Linq case JTokenType.Bytes: writer.WriteValue((byte[])_value); return; + case JTokenType.Guid: + case JTokenType.Uri: + case JTokenType.TimeSpan: + writer.WriteValue((_value != null) ? _value.ToString() : null); + return; } throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", _valueType, "Unexpected token type.");