Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/Newtonsoft.Json.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamesNK <james@newtonking.com>2008-02-28 12:32:09 +0300
committerJamesNK <james@newtonking.com>2008-02-28 12:32:09 +0300
commit3109027c75beca09701ade023cc0e5f4a439e380 (patch)
tree7e6da83b7660e5b9be61d78465cee3163c4f787e
parentc1ce4c366fb965c6028d0e766c542504e9a54ee1 (diff)
New features:
Added support for deserializing to an anonymous type with the DeserializeAnonymousType method. Support for reading, writing and serializing the new DateTimeOffset type. Added IsoDateTimeConverter. Converts DateTimes and DateTimeOffsets to and from the ISO 8601 format. Added JavaScriptDateTimeConverter. Converts DateTimes and DateTimeOffsets to and from a JavaScript date constructor. XmlNodeConverter handles serializing and deserializing JavaScript constructors. Ability to force XmlNodeConverter to write a value in an array. Logic is controlled by an attribute, json:Array="true". Changes: Dates are now serialized in a JSON complient manner, similar to ASP.NET's JavaScriptSerializer or WCF's DataContractJsonSerializer - http://weblogs.asp.net/bleroy/archive/2008/01/18/dates-and-json.aspx Removed the AspNetAjaxDateTimeConverter.
-rw-r--r--Src/Newtonsoft.Json.Tests/AspNetAjaxDateTimeConverterTest.cs70
-rw-r--r--Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs14
-rw-r--r--Src/Newtonsoft.Json.Tests/IsoDateTimeConverterTests.cs95
-rw-r--r--Src/Newtonsoft.Json.Tests/JavaScriptConvertTest.cs3
-rw-r--r--Src/Newtonsoft.Json.Tests/JavaScriptDateTimeConverterTests.cs57
-rw-r--r--Src/Newtonsoft.Json.Tests/JsonReaderTest.cs3
-rw-r--r--Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs86
-rw-r--r--Src/Newtonsoft.Json.Tests/JsonWriterTest.cs3
-rw-r--r--Src/Newtonsoft.Json.Tests/LinqToJsonTest.cs21
-rw-r--r--Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj9
-rw-r--r--Src/Newtonsoft.Json.Tests/TestFixtureBase.cs19
-rw-r--r--Src/Newtonsoft.Json.Tests/UtcDateTimeConverterTest.cs (renamed from Src/Newtonsoft.Json/Converters/AspNetAjaxDateTimeConverter.cs)37
-rw-r--r--Src/Newtonsoft.Json.Tests/XmlNodeConverterTest.cs94
-rw-r--r--Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs74
-rw-r--r--Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs64
-rw-r--r--Src/Newtonsoft.Json/Converters/JsonDateTimeSerializationMode.cs15
-rw-r--r--Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs72
-rw-r--r--Src/Newtonsoft.Json/JavaScriptConvert.cs67
-rw-r--r--Src/Newtonsoft.Json/JsonConverter.cs4
-rw-r--r--Src/Newtonsoft.Json/JsonReader.cs78
-rw-r--r--Src/Newtonsoft.Json/JsonSerializer.cs126
-rw-r--r--Src/Newtonsoft.Json/JsonWriter.cs9
-rw-r--r--Src/Newtonsoft.Json/Newtonsoft.Json.csproj5
-rw-r--r--Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs33
-rw-r--r--Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs2
25 files changed, 863 insertions, 197 deletions
diff --git a/Src/Newtonsoft.Json.Tests/AspNetAjaxDateTimeConverterTest.cs b/Src/Newtonsoft.Json.Tests/AspNetAjaxDateTimeConverterTest.cs
deleted file mode 100644
index f76ded5..0000000
--- a/Src/Newtonsoft.Json.Tests/AspNetAjaxDateTimeConverterTest.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-#region License
-// Copyright (c) 2007 James Newton-King
-//
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use,
-// copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following
-// conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using NUnit.Framework;
-using Newtonsoft.Json;
-using System.IO;
-using Newtonsoft.Json.Converters;
-
-namespace Newtonsoft.Json.Tests
-{
- [TestFixture]
- public class AspNetAjaxDateTimeConverterTest
- {
- public class DateTimeTestClass
- {
- public string PreField;
- public DateTime DateTimeField;
- public string PostField;
- }
-
- [Test]
- public void Serialize()
- {
- DateTimeTestClass c = new DateTimeTestClass();
- c.DateTimeField = new DateTime(2008, 12, 12, 12, 12, 12, 12);
- c.PreField = "Pre";
- c.PostField = "Post";
-
- string json = JavaScriptConvert.SerializeObject(c, new AspNetAjaxDateTimeConverter());
-
- Assert.AreEqual(@"{""PreField"":""Pre"",""DateTimeField"":""@1229083932012@"",""PostField"":""Post""}", json);
- }
-
- [Test]
- public void DeSerialize()
- {
- DateTimeTestClass c =
- JavaScriptConvert.DeserializeObject<DateTimeTestClass>(@"{""PreField"":""Pre"",""DateTimeField"":""@1229083932012@"",""PostField"":""Post""}", new AspNetAjaxDateTimeConverter());
-
- Assert.AreEqual(new DateTime(2008, 12, 12, 12, 12, 12, 12), c.DateTimeField);
- Assert.AreEqual("Pre", c.PreField);
- Assert.AreEqual("Post", c.PostField);
- }
- }
-} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs b/Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs
new file mode 100644
index 0000000..558a740
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Newtonsoft.Json.Tests
+{
+ public class DateTimeTestClass
+ {
+ public string PreField { get; set; }
+ public DateTime DateTimeField { get; set; }
+ public string PostField { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/IsoDateTimeConverterTests.cs b/Src/Newtonsoft.Json.Tests/IsoDateTimeConverterTests.cs
new file mode 100644
index 0000000..8b3580d
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/IsoDateTimeConverterTests.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Tests
+{
+ public class IsoDateTimeConverterTests : TestFixtureBase
+ {
+ [Test]
+ public void SerializeDateTime()
+ {
+ IsoDateTimeConverter converter = new IsoDateTimeConverter();
+
+ DateTime d = new DateTime(2000, 12, 15, 22, 11, 3, 55, DateTimeKind.Utc);
+ string result;
+
+ result = JavaScriptConvert.SerializeObject(d, converter);
+ Assert.AreEqual(@"""2000-12-15T22:11:03.0550000Z""", result);
+
+ Assert.AreEqual(d, JavaScriptConvert.DeserializeObject<DateTime>(result, converter));
+
+ d = new DateTime(2000, 12, 15, 22, 11, 3, 55, DateTimeKind.Local);
+ result = JavaScriptConvert.SerializeObject(d, converter);
+ Assert.AreEqual(@"""2000-12-15T22:11:03.0550000" + d.GetLocalOffset() + @"""", result);
+ }
+
+ [Test]
+ public void SerializeDateTimeOffset()
+ {
+ IsoDateTimeConverter converter = new IsoDateTimeConverter();
+
+ DateTimeOffset d = new DateTimeOffset(2000, 12, 15, 22, 11, 3, 55, TimeSpan.Zero);
+ string result;
+
+ result = JavaScriptConvert.SerializeObject(d, converter);
+ Assert.AreEqual(@"""2000-12-15T22:11:03.0550000+00:00""", result);
+
+ Assert.AreEqual(d, JavaScriptConvert.DeserializeObject<DateTimeOffset>(result, converter));
+ }
+
+ [Test]
+ public void SerializeUTC()
+ {
+ DateTimeTestClass c = new DateTimeTestClass();
+ c.DateTimeField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime();
+ c.PreField = "Pre";
+ c.PostField = "Post";
+ string json = JavaScriptConvert.SerializeObject(c, new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal });
+ Assert.AreEqual(@"{""PreField"":""Pre"",""DateTimeField"":""2008-12-12T12:12:12.0000000Z"",""PostField"":""Post""}", json);
+
+ //test the other edge case too
+ c.DateTimeField = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc).ToLocalTime();
+ c.PreField = "Pre";
+ c.PostField = "Post";
+ json = JavaScriptConvert.SerializeObject(c, new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal });
+ Assert.AreEqual(@"{""PreField"":""Pre"",""DateTimeField"":""2008-01-01T01:01:01.0000000Z"",""PostField"":""Post""}", json);
+ }
+
+ [Test]
+ public void DeserializeUTC()
+ {
+ DateTimeTestClass c =
+ JavaScriptConvert.DeserializeObject<DateTimeTestClass>(@"{""PreField"":""Pre"",""DateTimeField"":""2008-12-12T12:12:12Z"",""PostField"":""Post""}", new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal });
+
+ Assert.AreEqual(new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime(), c.DateTimeField);
+ Assert.AreEqual("Pre", c.PreField);
+ Assert.AreEqual("Post", c.PostField);
+
+ DateTimeTestClass c2 =
+ JavaScriptConvert.DeserializeObject<DateTimeTestClass>(@"{""PreField"":""Pre"",""DateTimeField"":""2008-01-01T01:01:01Z"",""PostField"":""Post""}", new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal });
+
+ Assert.AreEqual(new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc).ToLocalTime(), c2.DateTimeField);
+ Assert.AreEqual("Pre", c2.PreField);
+ Assert.AreEqual("Post", c2.PostField);
+ }
+
+ [Test]
+ public void SerializeShouldChangeNonUTCDates()
+ {
+ DateTimeTestClass c = new DateTimeTestClass();
+ c.DateTimeField = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Local);
+ c.PreField = "Pre";
+ c.PostField = "Post";
+ string json = JavaScriptConvert.SerializeObject(c, new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal }); //note that this fails without the Utc converter...
+ c.DateTimeField = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc);
+ string json2 = JavaScriptConvert.SerializeObject(c, new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal });
+ Assert.AreNotEqual(json, json2);
+ }
+ }
+} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/JavaScriptConvertTest.cs b/Src/Newtonsoft.Json.Tests/JavaScriptConvertTest.cs
index 63bf85b..917e23a 100644
--- a/Src/Newtonsoft.Json.Tests/JavaScriptConvertTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JavaScriptConvertTest.cs
@@ -6,8 +6,7 @@ using NUnit.Framework;
namespace Newtonsoft.Json.Tests
{
- [TestFixture]
- public class JavaScriptConvertTest
+ public class JavaScriptConvertTest : TestFixtureBase
{
[Test]
public void EscapeJavaScriptString()
diff --git a/Src/Newtonsoft.Json.Tests/JavaScriptDateTimeConverterTests.cs b/Src/Newtonsoft.Json.Tests/JavaScriptDateTimeConverterTests.cs
new file mode 100644
index 0000000..cf7288b
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/JavaScriptDateTimeConverterTests.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Newtonsoft.Json.Converters;
+
+namespace Newtonsoft.Json.Tests
+{
+ public class JavaScriptDateTimeConverterTests : TestFixtureBase
+ {
+ [Test]
+ public void SerializeDateTime()
+ {
+ JavaScriptDateTimeConverter converter = new JavaScriptDateTimeConverter();
+
+ DateTime d = new DateTime(2000, 12, 15, 22, 11, 3, 55, DateTimeKind.Utc);
+ string result;
+
+ result = JavaScriptConvert.SerializeObject(d, converter);
+ Assert.AreEqual("new Date(976918263055)", result);
+ }
+
+ [Test]
+ public void SerializeDateTimeOffset()
+ {
+ JavaScriptDateTimeConverter converter = new JavaScriptDateTimeConverter();
+
+ DateTimeOffset now = new DateTimeOffset(2000, 12, 15, 22, 11, 3, 55, TimeSpan.Zero);
+ string result;
+
+ result = JavaScriptConvert.SerializeObject(now, converter);
+ Assert.AreEqual("new Date(976918263055)", result);
+ }
+
+ [Test]
+ public void DeserializeDateTime()
+ {
+ JavaScriptDateTimeConverter converter = new JavaScriptDateTimeConverter();
+
+ DateTime result = JavaScriptConvert.DeserializeObject<DateTime>("new Date(976918263055)", converter);
+ Assert.AreEqual(new DateTime(2000, 12, 15, 22, 11, 3, 55, DateTimeKind.Utc), result);
+ }
+
+ [Test]
+ public void DeserializeDateTimeOffset()
+ {
+ JavaScriptDateTimeConverter converter = new JavaScriptDateTimeConverter();
+ DateTimeOffset start = new DateTimeOffset(2000, 12, 15, 22, 11, 3, 55, TimeSpan.Zero);
+
+ string json = JavaScriptConvert.SerializeObject(start, converter);
+
+ DateTimeOffset result = JavaScriptConvert.DeserializeObject<DateTimeOffset>(json, converter);
+ Assert.AreEqual(new DateTimeOffset(2000, 12, 15, 22, 11, 3, 55, TimeSpan.Zero), result);
+ }
+ }
+} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/JsonReaderTest.cs b/Src/Newtonsoft.Json.Tests/JsonReaderTest.cs
index 5bb32aa..f94a88a 100644
--- a/Src/Newtonsoft.Json.Tests/JsonReaderTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonReaderTest.cs
@@ -32,8 +32,7 @@ using System.IO;
namespace Newtonsoft.Json.Tests
{
- [TestFixture]
- public class JsonReaderTest
+ public class JsonReaderTest : TestFixtureBase
{
[Test]
public void YahooFinance()
diff --git a/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs
index c136129..a8ef48b 100644
--- a/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs
@@ -35,20 +35,25 @@ using System.Xml.Serialization;
using System.Collections.ObjectModel;
using System.Runtime.Serialization.Json;
using System.Net.Mail;
+using System.Web.Script.Serialization;
namespace Newtonsoft.Json.Tests
{
public class Product
{
public string Name;
- public DateTime Expiry;
+ public DateTime Expiry = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public decimal Price;
public string[] Sizes;
public override bool Equals(object obj)
{
if (obj is Product)
- return ((Product)obj).Name == Name;
+ {
+ Product p = (Product)obj;
+
+ return (p.Name == Name && p.Expiry == Expiry && p.Price == Price);
+ }
return base.Equals(obj);
}
@@ -74,7 +79,7 @@ namespace Newtonsoft.Json.Tests
public class Store
{
public StoreColor Color = StoreColor.Yellow;
- public DateTime Establised = new DateTime(2010, 1, 22);
+ public DateTimeOffset Establised = new DateTimeOffset(2010, 1, 22, 1, 1, 1, TimeSpan.Zero);
public double Width = 1.1;
public int Employees = 999;
public int[] RoomsPerFloor = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
@@ -94,7 +99,7 @@ namespace Newtonsoft.Json.Tests
Product rocket = new Product();
rocket.Name = "Rocket";
- rocket.Expiry = new DateTime(2000, 2, 2, 23, 1, 30);
+ rocket.Expiry = new DateTime(2000, 2, 2, 23, 1, 30, DateTimeKind.Utc);
Product alien = new Product();
alien.Name = "Alien";
@@ -111,8 +116,7 @@ namespace Newtonsoft.Json.Tests
White
}
- [TestFixture]
- public class JsonSerializerTest
+ public class JsonSerializerTest : TestFixtureBase
{
[Test]
public void PersonTypedObjectDeserialization()
@@ -627,6 +631,46 @@ keyword such as type of business.""
}
[Test]
+ public void DateTime()
+ {
+ List<DateTime> testDates = new List<DateTime> {
+ new DateTime(100, 1, 1, 1, 1, 1, DateTimeKind.Local),
+ new DateTime(100, 1, 1, 1, 1, 1, DateTimeKind.Unspecified),
+ new DateTime(100, 1, 1, 1, 1, 1, DateTimeKind.Utc),
+ new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Local),
+ new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Unspecified),
+ new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc),
+ };
+ string result;
+
+
+ MemoryStream ms = new MemoryStream();
+ DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List<DateTime>));
+ s.WriteObject(ms, testDates);
+ ms.Seek(0, SeekOrigin.Begin);
+ StreamReader sr = new StreamReader(ms);
+
+ string expected = sr.ReadToEnd();
+
+ result = JavaScriptConvert.SerializeObject(testDates);
+ Assert.AreEqual(expected, result);
+ }
+
+ [Test]
+ public void DateTimeOffset()
+ {
+ List<DateTimeOffset> testDates = new List<DateTimeOffset> {
+ new DateTimeOffset(new DateTime(100, 1, 1, 1, 1, 1, DateTimeKind.Utc)),
+ new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.Zero),
+ new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.FromHours(13)),
+ new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.FromHours(-3.5)),
+ };
+
+ string result = JavaScriptConvert.SerializeObject(testDates);
+ Assert.AreEqual(@"[""\/Date(-59011455539000+0000)\/"",""\/Date(946688461000+0000)\/"",""\/Date(946641661000+1300)\/"",""\/Date(946701061000-0330)\/""]", result);
+ }
+
+ [Test]
public void NonStringKeyDictionary()
{
Dictionary<int, int> values = new Dictionary<int, int>();
@@ -645,10 +689,27 @@ keyword such as type of business.""
[Test]
public void AnonymousObjectSerialization()
{
- var anonymous = new { StringValue = "I am a string", IntValue = int.MaxValue };
+ var anonymous =
+ new
+ {
+ StringValue = "I am a string",
+ IntValue = int.MaxValue,
+ NestedAnonymous = new { NestedValue = byte.MaxValue },
+ NestedArray = new[] { 1, 2 },
+ Product = new Product() { Name = "TestProduct" }
+ };
string json = JavaScriptConvert.SerializeObject(anonymous);
- Assert.AreEqual(@"{""StringValue"":""I am a string"",""IntValue"":2147483647}", json);
+ Assert.AreEqual(@"{""StringValue"":""I am a string"",""IntValue"":2147483647,""NestedAnonymous"":{""NestedValue"":255},""NestedArray"":[1,2],""Product"":{""Name"":""TestProduct"",""Expiry"":""\/Date(946684800000)\/"",""Price"":0,""Sizes"":null}}", json);
+
+ anonymous = JavaScriptConvert.DeserializeAnonymousType(json, anonymous);
+ Assert.AreEqual("I am a string", anonymous.StringValue);
+ Assert.AreEqual(int.MaxValue, anonymous.IntValue);
+ Assert.AreEqual(255, anonymous.NestedAnonymous.NestedValue);
+ Assert.AreEqual(2, anonymous.NestedArray.Length);
+ Assert.AreEqual(1, anonymous.NestedArray[0]);
+ Assert.AreEqual(2, anonymous.NestedArray[1]);
+ Assert.AreEqual("TestProduct", anonymous.Product.Name);
}
[Test]
@@ -668,7 +729,7 @@ keyword such as type of business.""
jsonSerializer.Serialize(sw, collection);
- Assert.AreEqual(@"[{""Name"":""Test1"",""Expiry"":new Date(-59011459200000),""Price"":0,""Sizes"":null},{""Name"":""Test2"",""Expiry"":new Date(-59011459200000),""Price"":0,""Sizes"":null},{""Name"":""Test3"",""Expiry"":new Date(-59011459200000),""Price"":0,""Sizes"":null}]",
+ Assert.AreEqual(@"[{""Name"":""Test1"",""Expiry"":""\/Date(946684800000)\/"",""Price"":0,""Sizes"":null},{""Name"":""Test2"",""Expiry"":""\/Date(946684800000)\/"",""Price"":0,""Sizes"":null},{""Name"":""Test3"",""Expiry"":""\/Date(946684800000)\/"",""Price"":0,""Sizes"":null}]",
sw.GetStringBuilder().ToString());
ProductCollection collectionNew = (ProductCollection)jsonSerializer.Deserialize(new JsonReader(new StringReader(sw.GetStringBuilder().ToString())), typeof(ProductCollection));
@@ -687,13 +748,18 @@ keyword such as type of business.""
StringWriter sw = new StringWriter();
jsonSerializer.Serialize(sw, s1);
- Assert.AreEqual(@"{""Color"":2,""Establised"":new Date(1264118400000),""Width"":1.1,""Employees"":999,""RoomsPerFloor"":[1,2,3,4,5,6,7,8,9],""Open"":false,""Symbol"":""@"",""Mottos"":[""Hello World"",""öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~"",null,"" ""],""Cost"":100980.1,""Escape"":""\r\n\t\f\b?{\\r\\n\""'"",""product"":[{""Name"":""Rocket"",""Expiry"":new Date(949532490000),""Price"":0},{""Name"":""Alien"",""Expiry"":new Date(-59011459200000),""Price"":0}]}", sw.GetStringBuilder().ToString());
+ //JavaScriptConvert.ConvertDateTimeToJavaScriptTicks(s1.Establised.DateTime)
+
+ Assert.AreEqual(@"{""Color"":2,""Establised"":""\/Date(1264122061000+0000)\/"",""Width"":1.1,""Employees"":999,""RoomsPerFloor"":[1,2,3,4,5,6,7,8,9],""Open"":false,""Symbol"":""@"",""Mottos"":[""Hello World"",""öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~"",null,"" ""],""Cost"":100980.1,""Escape"":""\r\n\t\f\b?{\\r\\n\""'"",""product"":[{""Name"":""Rocket"",""Expiry"":""\/Date(949532490000)\/"",""Price"":0},{""Name"":""Alien"",""Expiry"":""\/Date(946684800000)\/"",""Price"":0}]}", sw.GetStringBuilder().ToString());
Store s2 = (Store)jsonSerializer.Deserialize(new JsonReader(new StringReader("{}")), typeof(Store));
Assert.AreEqual("\r\n\t\f\b?{\\r\\n\"\'", s2.Escape);
Store s3 = (Store)jsonSerializer.Deserialize(new JsonReader(new StringReader(@"{""Escape"":null}")), typeof(Store));
Assert.AreEqual("\r\n\t\f\b?{\\r\\n\"\'", s3.Escape);
+
+ Store s4 = (Store)jsonSerializer.Deserialize(new JsonReader(new StringReader(@"{""Color"":2,""Establised"":""\/Date(1264071600000+1300)\/"",""Width"":1.1,""Employees"":999,""RoomsPerFloor"":[1,2,3,4,5,6,7,8,9],""Open"":false,""Symbol"":""@"",""Mottos"":[""Hello World"",""öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~"",null,"" ""],""Cost"":100980.1,""Escape"":""\r\n\t\f\b?{\\r\\n\""'"",""product"":[{""Name"":""Rocket"",""Expiry"":""\/Date(949485690000+1300)\/"",""Price"":0},{""Name"":""Alien"",""Expiry"":""\/Date(946638000000)\/"",""Price"":0}]}")), typeof(Store));
+ Assert.AreEqual(s1.Establised, s3.Establised);
}
}
} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/JsonWriterTest.cs b/Src/Newtonsoft.Json.Tests/JsonWriterTest.cs
index 5bb8aeb..4ca2273 100644
--- a/Src/Newtonsoft.Json.Tests/JsonWriterTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonWriterTest.cs
@@ -32,8 +32,7 @@ using System.IO;
namespace Newtonsoft.Json.Tests
{
- [TestFixture]
- public class JsonWriterTest
+ public class JsonWriterTest : TestFixtureBase
{
[Test]
public void ValueFormatting()
diff --git a/Src/Newtonsoft.Json.Tests/LinqToJsonTest.cs b/Src/Newtonsoft.Json.Tests/LinqToJsonTest.cs
index 21df18f..9426abc 100644
--- a/Src/Newtonsoft.Json.Tests/LinqToJsonTest.cs
+++ b/Src/Newtonsoft.Json.Tests/LinqToJsonTest.cs
@@ -34,8 +34,7 @@ using System.IO;
namespace Newtonsoft.Json.Tests
{
- [TestFixture]
- public class LinqToJsonTest
+ public class LinqToJsonTest : TestFixtureBase
{
[Test]
public void ObjectParse()
@@ -226,12 +225,16 @@ keyword such as type of business.""
[Test]
public void JTokenToStringTypes()
{
- string json = @"{""Color"":2,""Establised"":new Date(1264118400000),""Width"":1.1,""Employees"":999,""RoomsPerFloor"":[1,2,3,4,5,6,7,8,9],""Open"":false,""Symbol"":""@"",""Mottos"":[""Hello World"",""öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~"",null,"" ""],""Cost"":100980.1,""Escape"":""\r\n\t\f\b?{\\r\\n\""'"",""product"":[{""Name"":""Rocket"",""Expiry"":new Date(949532490000),""Price"":0},{""Name"":""Alien"",""Expiry"":new Date(-59011459200000),""Price"":0}]}";
+ string json = @"{""Color"":2,""Establised"":new Date(1264118400000),""Width"":1.1,""Employees"":999,""RoomsPerFloor"":[1,2,3,4,5,6,7,8,9],""Open"":false,""Symbol"":""@"",""Mottos"":[""Hello World"",""öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~"",null,"" ""],""Cost"":100980.1,""Escape"":""\r\n\t\f\b?{\\r\\n\""'"",""product"":[{""Name"":""Rocket"",""Expiry"":new Date(949532490000),""Price"":0},{""Name"":""Alien"",""Expiry"":new Date(-62135596800000),""Price"":0}]}";
JObject o = JObject.Parse(json);
- Assert.AreEqual(@"""Establised"": new Date(1264118400000)", o.Property("Establised").ToString());
- Assert.AreEqual(@"new Date(1264118400000)", o.Property("Establised").Value.ToString());
+ Assert.AreEqual(@"""Establised"": new Date(
+ 1264118400000
+)", o.Property("Establised").ToString());
+ Assert.AreEqual(@"new Date(
+ 1264118400000
+)", o.Property("Establised").Value.ToString());
Assert.AreEqual(@"""Width"": 1.1", o.Property("Width").ToString());
Assert.AreEqual(@"1.1", o.Property("Width").Value.ToString());
Assert.AreEqual(@"""Open"": false", o.Property("Open").ToString());
@@ -271,13 +274,13 @@ keyword such as type of business.""
JArray a =
new JArray(
o,
- new DateTime(2000, 10, 10),
+ new DateTime(2000, 10, 10, 0, 0, 0, DateTimeKind.Utc),
55,
new JArray(
"1",
2,
3.0,
- new DateTime(4, 5, 6, 7, 8, 9)
+ new DateTime(4, 5, 6, 7, 8, 9, DateTimeKind.Utc)
),
new JConstructor(
"ConstructorName",
@@ -295,13 +298,13 @@ keyword such as type of business.""
""Test3"": ""Test3Value"",
""Test4"": null
},
- new Date(971136000000),
+ ""\/Date(971136000000)\/"",
55,
[
""1"",
2,
3,
- new Date(-59011459200000)
+ ""\/Date(-62030076711000)\/""
],
new ConstructorName(
""param1"",
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
index c66a51e..2af957f 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
@@ -60,16 +60,23 @@
<Reference Include="System.ServiceModel.Web">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
+ <Reference Include="System.Web.Extensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="AspNetAjaxDateTimeConverterTest.cs" />
+ <Compile Include="DateTimeTestClass.cs" />
+ <Compile Include="IsoDateTimeConverterTests.cs" />
<Compile Include="JavaScriptConvertTest.cs" />
+ <Compile Include="JavaScriptDateTimeConverterTests.cs" />
<Compile Include="JsonReaderTest.cs" />
<Compile Include="JsonSerializerTest.cs" />
<Compile Include="JsonWriterTest.cs" />
<Compile Include="LinqToJsonTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="TestFixtureBase.cs" />
+ <Compile Include="UtcDateTimeConverterTest.cs" />
<Compile Include="XmlNodeConverterTest.cs" />
</ItemGroup>
<ItemGroup>
diff --git a/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs b/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs
new file mode 100644
index 0000000..6b0b9a9
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+
+namespace Newtonsoft.Json.Tests
+{
+ [TestFixture]
+ public abstract class TestFixtureBase
+ {
+ public string GetOffset(DateTime value)
+ {
+ TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(value.ToLocalTime());
+
+ return utcOffset.Hours.ToString("+00;-00") + utcOffset.Minutes.ToString("00;00");
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json/Converters/AspNetAjaxDateTimeConverter.cs b/Src/Newtonsoft.Json.Tests/UtcDateTimeConverterTest.cs
index eaaf83f..b71eb96 100644
--- a/Src/Newtonsoft.Json/Converters/AspNetAjaxDateTimeConverter.cs
+++ b/Src/Newtonsoft.Json.Tests/UtcDateTimeConverterTest.cs
@@ -23,37 +23,26 @@
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
-
using System;
using System.Collections.Generic;
using System.Text;
+using NUnit.Framework;
+using Newtonsoft.Json;
+using System.IO;
+using Newtonsoft.Json.Converters;
+using System.Xml;
using System.Globalization;
-namespace Newtonsoft.Json.Converters
+namespace Newtonsoft.Json.Tests
{
- public class AspNetAjaxDateTimeConverter : JsonConverter
+ public class IsoDateTimeConverterTest : TestFixtureBase
{
- public override void WriteJson(JsonWriter writer, object value)
- {
- DateTime dateTime = (DateTime)value;
- long javaScriptTicks = JavaScriptConvert.ConvertDateTimeToJavaScriptTicks(dateTime);
-
- writer.WriteValue("@" + javaScriptTicks.ToString(null, CultureInfo.InvariantCulture) + "@");
- }
-
- public override object ReadJson(JsonReader reader, Type objectType)
- {
- string dateTimeText = (string)reader.Value;
- dateTimeText = dateTimeText.Substring(1, dateTimeText.Length - 2);
-
- long javaScriptTicks = Convert.ToInt64(dateTimeText);
-
- return JavaScriptConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
- }
-
- public override bool CanConvert(Type valueType)
+ [Test]
+ public void ShouldBeAbleToConvertDateTimes()
{
- return typeof(DateTime).IsAssignableFrom(valueType);
+ IsoDateTimeConverter conv = new IsoDateTimeConverter();
+ Assert.IsTrue(conv.CanConvert(typeof(DateTime)));
+ Assert.IsTrue(conv.CanConvert(typeof(DateTimeOffset)));
}
}
-}
+} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/XmlNodeConverterTest.cs b/Src/Newtonsoft.Json.Tests/XmlNodeConverterTest.cs
index 21b4bcd..65ef870 100644
--- a/Src/Newtonsoft.Json.Tests/XmlNodeConverterTest.cs
+++ b/Src/Newtonsoft.Json.Tests/XmlNodeConverterTest.cs
@@ -29,11 +29,11 @@ using Newtonsoft.Json;
using System.IO;
using System.Xml;
using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Tests
{
- [TestFixture]
- public class XmlNodeConverterTest
+ public class XmlNodeConverterTest : TestFixtureBase
{
[Test]
public void DocumentSerializeIndented()
@@ -210,7 +210,7 @@ namespace Newtonsoft.Json.Tests
string jsonText = JavaScriptConvert.SerializeXmlNode(doc);
- XmlDocument deserializedDoc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
+ XmlDocument deserializedDoc = (XmlDocument)JavaScriptConvert.DeserializeXmlNode(jsonText);
Assert.AreEqual(doc.InnerXml, deserializedDoc.InnerXml);
@@ -242,7 +242,7 @@ namespace Newtonsoft.Json.Tests
}
}";
- XmlDocument doc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
+ XmlDocument doc = (XmlDocument)JavaScriptConvert.DeserializeXmlNode(jsonText);
string expected = @"<?xml version=""1.0"" standalone=""no""?>
<span class=""vevent"">
@@ -295,7 +295,7 @@ namespace Newtonsoft.Json.Tests
string jsonText = JavaScriptConvert.SerializeXmlNode(doc);
- XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
+ XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeserializeXmlNode(jsonText);
Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);
}
@@ -322,7 +322,7 @@ namespace Newtonsoft.Json.Tests
Console.WriteLine(jsonText);
- XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
+ XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeserializeXmlNode(jsonText);
Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);
}
@@ -330,13 +330,89 @@ namespace Newtonsoft.Json.Tests
[Test]
public void OtherElementDataTypes()
{
- string jsonText = @"{""?xml"":{""@version"":""1.0"",""@standalone"":""no""},""root"":{""person"":[{""@id"":""1"",""Float"":2.5,""Integer"":99},{""@id"":""2"",""Boolean"":true,""date"":new Date(954374400000)}]}}";
+ string jsonText = @"{""?xml"":{""@version"":""1.0"",""@standalone"":""no""},""root"":{""person"":[{""@id"":""1"",""Float"":2.5,""Integer"":99},{""@id"":""2"",""Boolean"":true,""date"":""\/Date(954374400000)\/""}]}}";
- XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
+ XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeserializeXmlNode(jsonText);
- string expected = @"<?xml version=""1.0"" standalone=""no""?><root><person id=""1""><Float>2.5</Float><Integer>99</Integer></person><person id=""2""><Boolean>true</Boolean><date>2000-03-30T00:00:00.0000000+13:00</date></person></root>";
+ string expected = @"<?xml version=""1.0"" standalone=""no""?><root><person id=""1""><Float>2.5</Float><Integer>99</Integer></person><person id=""2""><Boolean>true</Boolean><date>2000-03-30T00:00:00Z</date></person></root>";
Assert.AreEqual(expected, newDoc.InnerXml);
}
+
+ [Test]
+ [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "XmlNodeConverter can only convert JSON that begins with an object.")]
+ public void NoRootObject()
+ {
+ XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeserializeXmlNode(@"[1]");
+ }
+
+ [Test]
+ [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "JSON root object has multiple properties.")]
+ public void RootObjectMultipleProperties()
+ {
+ XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeserializeXmlNode(@"{Prop1:1,Prop2:2}");
+ }
+
+ [Test]
+ public void JavaScriptConstructor()
+ {
+ string jsonText = @"{root:{r:new Date(34343, 55)}}";
+
+ XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeserializeXmlNode(jsonText);
+
+ string expected = @"<root><r><-Date>34343</-Date><-Date>55</-Date></r></root>";
+
+ Assert.AreEqual(expected, newDoc.InnerXml);
+
+ string json = JavaScriptConvert.SerializeXmlNode(newDoc);
+ Assert.AreEqual(@"{""root"":{""r"":new Date(""34343"",""55"")}}", json);
+ }
+
+ [Test]
+ public void ForceJsonArray()
+ {
+ string arrayXml = @"<root xmlns:json=""http://james.newtonking.com/projects/json"">
+ <person id=""1"">
+ <name>Alan</name>
+ <url>http://www.google.com</url>
+ <role json:Array=""true"">Admin</role>
+ </person>
+ </root>";
+
+ XmlDocument arrayDoc = new XmlDocument();
+ arrayDoc.LoadXml(arrayXml);
+
+ string arrayJsonText = JavaScriptConvert.SerializeXmlNode(arrayDoc);
+ Assert.AreEqual(@"{""root"":{""person"":{""@id"":""1"",""name"":""Alan"",""url"":""http://www.google.com"",""role"":[""Admin""]}}}", arrayJsonText);
+
+ arrayXml = @"<root xmlns:json=""http://james.newtonking.com/projects/json"">
+ <person id=""1"">
+ <name>Alan</name>
+ <url>http://www.google.com</url>
+ <role json:Array=""true"">Admin1</role>
+ <role json:Array=""true"">Admin2</role>
+ </person>
+ </root>";
+
+ arrayDoc = new XmlDocument();
+ arrayDoc.LoadXml(arrayXml);
+
+ arrayJsonText = JavaScriptConvert.SerializeXmlNode(arrayDoc);
+ Assert.AreEqual(@"{""root"":{""person"":{""@id"":""1"",""name"":""Alan"",""url"":""http://www.google.com"",""role"":[""Admin1"",""Admin2""]}}}", arrayJsonText);
+
+ arrayXml = @"<root xmlns:json=""http://james.newtonking.com/projects/json"">
+ <person id=""1"">
+ <name>Alan</name>
+ <url>http://www.google.com</url>
+ <role json:Array=""false"">Admin1</role>
+ </person>
+ </root>";
+
+ arrayDoc = new XmlDocument();
+ arrayDoc.LoadXml(arrayXml);
+
+ arrayJsonText = JavaScriptConvert.SerializeXmlNode(arrayDoc);
+ Assert.AreEqual(@"{""root"":{""person"":{""@id"":""1"",""name"":""Alan"",""url"":""http://www.google.com"",""role"":""Admin1""}}}", arrayJsonText);
+ }
}
} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs b/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs
new file mode 100644
index 0000000..8d06729
--- /dev/null
+++ b/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Converters
+{
+ public class IsoDateTimeConverter : JsonConverter
+ {
+ private const string DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
+
+ private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind;
+ //private bool _forceUniversalTime;
+
+ //public bool ForceUniversalTime
+ //{
+ // get { return _forceUniversalTime; }
+ // set { _forceUniversalTime = value; }
+ //}
+
+ public DateTimeStyles DateTimeStyles
+ {
+ get { return _dateTimeStyles; }
+ set { _dateTimeStyles = value; }
+ }
+
+ public override void WriteJson(JsonWriter writer, object value)
+ {
+ string text;
+
+ if (value is DateTime)
+ {
+ DateTime dateTime = (DateTime)value;
+
+ if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
+ || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
+ dateTime = dateTime.ToUniversalTime();
+
+ text = dateTime.ToString(DateTimeFormat, CultureInfo.InvariantCulture);
+ }
+ else
+ {
+ DateTimeOffset dateTimeOffset = (DateTimeOffset)value;
+ if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
+ || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
+ dateTimeOffset = dateTimeOffset.ToUniversalTime();
+
+ text = dateTimeOffset.ToString(DateTimeFormat, CultureInfo.InvariantCulture);
+ }
+
+ writer.WriteValue(text);
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType)
+ {
+ if (reader.TokenType != JsonToken.String)
+ throw new Exception(string.Format("Unexpected token parsing date. Expected String, got {0}.", reader.TokenType));
+
+ string dateText = reader.Value.ToString();
+
+ if (objectType == typeof(DateTimeOffset))
+ return DateTimeOffset.Parse(dateText, CultureInfo.InvariantCulture, _dateTimeStyles);
+
+ return DateTime.Parse(dateText, CultureInfo.InvariantCulture, _dateTimeStyles);
+ }
+
+ public override bool CanConvert(Type objectType)
+ {
+ return (typeof(DateTime).IsAssignableFrom(objectType)
+ || typeof(DateTimeOffset).IsAssignableFrom(objectType));
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs b/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs
new file mode 100644
index 0000000..e74698c
--- /dev/null
+++ b/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Converters
+{
+ public class JavaScriptDateTimeConverter : JsonConverter
+ {
+ public override void WriteJson(JsonWriter writer, object value)
+ {
+ long ticks;
+
+ if (value is DateTime)
+ {
+ DateTime dateTime = (DateTime)value;
+ DateTime utcDateTime = dateTime.ToUniversalTime();
+ ticks = JavaScriptConvert.ConvertDateTimeToJavaScriptTicks(utcDateTime);
+ }
+ else
+ {
+ DateTimeOffset dateTimeOffset = (DateTimeOffset)value;
+ DateTimeOffset utcDateTimeOffset = dateTimeOffset.ToUniversalTime();
+ ticks = JavaScriptConvert.ConvertDateTimeToJavaScriptTicks(utcDateTimeOffset.UtcDateTime);
+ }
+
+ writer.WriteStartConstructor("Date");
+ writer.WriteValue(ticks);
+ writer.WriteEndConstructor();
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType)
+ {
+ if (reader.TokenType != JsonToken.StartConstructor || string.Compare(reader.Value.ToString(), "Date", StringComparison.Ordinal) != 0)
+ throw new Exception(string.Format("Unexpected token or value when parsing date. Token: {0}, Value: {1}", reader.TokenType, reader.Value));
+
+ reader.Read();
+
+ if (reader.TokenType != JsonToken.Integer)
+ throw new Exception(string.Format("Unexpected token parsing date. Expected Integer, got {0}.", reader.TokenType));
+
+ long ticks = (long)reader.Value;
+
+ DateTime d = JavaScriptConvert.ConvertJavaScriptTicksToDateTime(ticks);
+
+ reader.Read();
+
+ if (reader.TokenType != JsonToken.EndConstructor)
+ throw new Exception(string.Format("Unexpected token parsing date. Expected EndConstructor, got {0}.", reader.TokenType));
+
+ if (objectType == typeof(DateTimeOffset))
+ return new DateTimeOffset(d);
+
+ return d;
+ }
+
+ public override bool CanConvert(Type objectType)
+ {
+ return (typeof(DateTime).IsAssignableFrom(objectType)
+ || typeof(DateTimeOffset).IsAssignableFrom(objectType));
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json/Converters/JsonDateTimeSerializationMode.cs b/Src/Newtonsoft.Json/Converters/JsonDateTimeSerializationMode.cs
new file mode 100644
index 0000000..4b9f310
--- /dev/null
+++ b/Src/Newtonsoft.Json/Converters/JsonDateTimeSerializationMode.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Newtonsoft.Json.Converters
+{
+ public enum JsonDateTimeSerializationMode
+ {
+ Local,
+ Utc,
+ Unspecified,
+ RoundtripKind
+ }
+} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs
index 3c5a7ad..0ff6a1f 100644
--- a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs
+++ b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs
@@ -29,6 +29,7 @@ using System.Text;
using System.Drawing;
using System.Xml;
using Newtonsoft.Json.Utilities;
+using System.Linq;
namespace Newtonsoft.Json.Converters
{
@@ -40,6 +41,7 @@ namespace Newtonsoft.Json.Converters
private const string WhitespaceName = "#whitespace";
private const string SignificantWhitespaceName = "#significant-whitespace";
private const string DeclarationName = "?xml";
+ private const string JsonNamespaceUri = "http://james.newtonking.com/projects/json";
#region Writing
public override void WriteJson(JsonWriter writer, object value)
@@ -106,13 +108,29 @@ namespace Newtonsoft.Json.Converters
foreach (KeyValuePair<string, List<XmlNode>> nodeNameGroup in nodesGroupedByName)
{
List<XmlNode> groupedNodes = nodeNameGroup.Value;
+ bool writeArray;
if (groupedNodes.Count == 1)
{
+ XmlNode singleNode = groupedNodes[0];
+ XmlAttribute jsonArrayAttribute = (singleNode.Attributes != null) ? singleNode.Attributes["Array", JsonNamespaceUri] : null;
+ if (jsonArrayAttribute != null)
+ writeArray = XmlConvert.ToBoolean(jsonArrayAttribute.Value);
+ else
+ writeArray = false;
+ }
+ else
+ {
+ writeArray = true;
+ }
+
+ if (!writeArray)
+ {
SerializeNode(writer, groupedNodes[0], true);
}
else
{
+ string elementNames = nodeNameGroup.Key;
writer.WritePropertyName(nodeNameGroup.Key);
writer.WriteStartArray();
@@ -138,7 +156,7 @@ namespace Newtonsoft.Json.Converters
if (writePropertyName)
writer.WritePropertyName(node.Name);
- if (CollectionUtils.IsNullOrEmpty(node.Attributes) && node.ChildNodes.Count == 1
+ if (ValueAttributes(node.Attributes).Count() == 0 && node.ChildNodes.Count == 1
&& node.ChildNodes[0].NodeType == XmlNodeType.Text)
{
// write elements with a single text child as a name value pair
@@ -149,6 +167,20 @@ namespace Newtonsoft.Json.Converters
// empty element
writer.WriteNull();
}
+ else if (node.ChildNodes.OfType<XmlElement>().Where(x => x.Name.StartsWith("-")).Count() > 1)
+ {
+ XmlElement constructorValueElement = node.ChildNodes.OfType<XmlElement>().Where(x => x.Name.StartsWith("-")).First();
+ string constructorName = constructorValueElement.Name.Substring(1);
+
+ writer.WriteStartConstructor(constructorName);
+
+ for (int i = 0; i < node.ChildNodes.Count; i++)
+ {
+ SerializeNode(writer, node.ChildNodes[i], false);
+ }
+
+ writer.WriteEndConstructor();
+ }
else
{
writer.WriteStartObject();
@@ -174,6 +206,11 @@ namespace Newtonsoft.Json.Converters
case XmlNodeType.ProcessingInstruction:
case XmlNodeType.Whitespace:
case XmlNodeType.SignificantWhitespace:
+ if (node.Prefix == "xmlns" && node.Value == JsonNamespaceUri)
+ break;
+ else if (node.NamespaceURI == JsonNamespaceUri)
+ break;
+
if (writePropertyName)
writer.WritePropertyName(GetPropertyName(node));
writer.WriteValue(node.Value);
@@ -216,6 +253,10 @@ namespace Newtonsoft.Json.Converters
XmlDocument document = new XmlDocument();
XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
+
+ if (reader.TokenType != JsonToken.StartObject)
+ throw new JsonSerializationException("XmlNodeConverter can only convert JSON that begins with an object.");
+
reader.Read();
DeserializeNode(reader, document, manager, document);
@@ -241,7 +282,7 @@ namespace Newtonsoft.Json.Converters
break;
default:
// processing instructions and the xml declaration start with ?
- if (propertyName[0] == '?')
+ if (!string.IsNullOrEmpty(propertyName) && propertyName[0] == '?')
{
if (propertyName == DeclarationName)
{
@@ -292,7 +333,8 @@ namespace Newtonsoft.Json.Converters
&& reader.TokenType != JsonToken.Boolean
&& reader.TokenType != JsonToken.Integer
&& reader.TokenType != JsonToken.Float
- && reader.TokenType != JsonToken.Date)
+ && reader.TokenType != JsonToken.Date
+ && reader.TokenType != JsonToken.StartConstructor)
{
// read properties until first non-attribute is encountered
while (!finishedAttributes && !finishedElement && reader.Read())
@@ -370,7 +412,8 @@ namespace Newtonsoft.Json.Converters
}
else if (reader.TokenType == JsonToken.Date)
{
- element.AppendChild(document.CreateTextNode(XmlConvert.ToString((DateTime)reader.Value)));
+ DateTime d = (DateTime)reader.Value;
+ element.AppendChild(document.CreateTextNode(XmlConvert.ToString(d, DateTimeUtils.ToSerializationMode(d.Kind))));
}
else if (reader.TokenType == JsonToken.Null)
{
@@ -400,6 +443,9 @@ namespace Newtonsoft.Json.Converters
switch (reader.TokenType)
{
case JsonToken.PropertyName:
+ if (currentNode.NodeType == XmlNodeType.Document && document.DocumentElement != null)
+ throw new JsonSerializationException("JSON root object has multiple properties.");
+
string propertyName = reader.Value.ToString();
reader.Read();
@@ -415,6 +461,14 @@ namespace Newtonsoft.Json.Converters
DeserializeValue(reader, document, manager, propertyName, currentNode);
}
break;
+ case JsonToken.StartConstructor:
+ string constructorName = reader.Value.ToString();
+
+ while (reader.Read() && reader.TokenType != JsonToken.EndConstructor)
+ {
+ DeserializeValue(reader, document, manager, "-" + constructorName, currentNode);
+ }
+ break;
case JsonToken.EndObject:
case JsonToken.EndArray:
return;
@@ -459,6 +513,16 @@ namespace Newtonsoft.Json.Converters
else
return qualifiedName.Substring(0, colonPosition);
}
+
+ private IEnumerable<XmlAttribute> ValueAttributes(XmlAttributeCollection c)
+ {
+ return c.OfType<XmlAttribute>().Where(a => a.NamespaceURI != JsonNamespaceUri);
+ }
+
+ private IEnumerable<XmlNode> ValueNodes(XmlNodeList c)
+ {
+ return c.OfType<XmlNode>().Where(n => n.NamespaceURI != JsonNamespaceUri);
+ }
#endregion
public override bool CanConvert(Type valueType)
diff --git a/Src/Newtonsoft.Json/JavaScriptConvert.cs b/Src/Newtonsoft.Json/JavaScriptConvert.cs
index ea1f7df..5bb4638 100644
--- a/Src/Newtonsoft.Json/JavaScriptConvert.cs
+++ b/Src/Newtonsoft.Json/JavaScriptConvert.cs
@@ -75,7 +75,7 @@ namespace Newtonsoft.Json
Null = "null";
Undefined = "undefined";
- InitialJavaScriptDateTicks = (new DateTime(1970, 1, 1)).Ticks;
+ InitialJavaScriptDateTicks = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).Ticks;
MinimumJavaScriptDate = new DateTime(100, 1, 1);
}
@@ -86,24 +86,53 @@ namespace Newtonsoft.Json
/// <returns>A Json string representation of the <see cref="DateTime"/>.</returns>
public static string ToString(DateTime value)
{
+ return ToStringInternal(new DateTimeOffset(value), value.Kind);
+ }
+
+ /// <summary>
+ /// Converts the <see cref="DateTimeOffset"/> to it's JavaScript string representation.
+ /// </summary>
+ /// <param name="value">The value to convert.</param>
+ /// <returns>A Json string representation of the <see cref="DateTimeOffset"/>.</returns>
+ public static string ToString(DateTimeOffset value)
+ {
+ return ToStringInternal(value, DateTimeKind.Local);
+ }
+
+ public static string ToStringInternal(DateTimeOffset value, DateTimeKind kind)
+ {
long javaScriptTicks = ConvertDateTimeToJavaScriptTicks(value);
- return "new Date(" + javaScriptTicks + ")";
+ string offset;
+ switch (kind)
+ {
+ case DateTimeKind.Local:
+ case DateTimeKind.Unspecified:
+ TimeSpan utcOffset = value.Offset;
+ offset = utcOffset.Hours.ToString("+00;-00") + utcOffset.Minutes.ToString("00;00");
+ break;
+ default:
+ offset = string.Empty;
+ break;
+ }
+ return @"""\/Date(" + javaScriptTicks.ToString(CultureInfo.InvariantCulture) + offset + @")\/""";
}
- internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime)
+ internal static long ConvertDateTimeToJavaScriptTicks(DateTimeOffset dateTime)
{
- if (dateTime < MinimumJavaScriptDate)
- dateTime = MinimumJavaScriptDate;
+ DateTimeOffset utcDateTime = dateTime.ToUniversalTime();
- long javaScriptTicks = (dateTime.Ticks - InitialJavaScriptDateTicks) / (long)10000;
+ //if (utcDateTime < MinimumJavaScriptDate)
+ // utcDateTime = MinimumJavaScriptDate;
+
+ long javaScriptTicks = (utcDateTime.Ticks - InitialJavaScriptDateTicks) / (long)10000;
return javaScriptTicks;
}
internal static DateTime ConvertJavaScriptTicksToDateTime(long javaScriptTicks)
{
- DateTime dateTime = new DateTime((javaScriptTicks * 10000) + InitialJavaScriptDateTicks);
+ DateTime dateTime = new DateTime((javaScriptTicks * 10000) + InitialJavaScriptDateTicks, DateTimeKind.Utc);
return dateTime;
}
@@ -328,6 +357,10 @@ namespace Newtonsoft.Json
return ToString((decimal)convertible);
}
}
+ else if (value is DateTimeOffset)
+ {
+ return ToString((DateTimeOffset)value);
+ }
throw new ArgumentException(string.Format("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.", value.GetType()));
}
@@ -397,12 +430,28 @@ namespace Newtonsoft.Json
}
/// <summary>
+ /// Deserializes the specified JSON to the given anonymous type.
+ /// </summary>
+ /// <typeparam name="T">
+ /// The anonymous type to deserialize to. This can't be specified
+ /// traditionally and must be infered from the anonymous type passed
+ /// as a parameter.
+ /// </typeparam>
+ /// <param name="value">The object to deserialize.</param>
+ /// <param name="anonymousTypeObject">The anonymous type object.</param>
+ /// <returns>The deserialized anonymous type from the JSON string.</returns>
+ public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
+ {
+ return (T)DeserializeObject(value, typeof(T));
+ }
+
+ /// <summary>
/// Deserializes the specified object to a Json object.
/// </summary>
/// <typeparam name="T">The type of the object to deserialize.</typeparam>
/// <param name="value">The object to deserialize.</param>
/// <param name="converters">Converters to use while deserializing.</param>
- /// <returns>The deserialized object from the Json string.</returns>
+ /// <returns>The deserialized object from the JSON string.</returns>
public static T DeserializeObject<T>(string value, params JsonConverter[] converters)
{
return (T)DeserializeObject(value, typeof(T), converters);
@@ -438,7 +487,7 @@ namespace Newtonsoft.Json
return SerializeObject(node, converter);
}
- public static XmlNode DeerializeXmlNode(string value)
+ public static XmlNode DeserializeXmlNode(string value)
{
XmlNodeConverter converter = new XmlNodeConverter();
diff --git a/Src/Newtonsoft.Json/JsonConverter.cs b/Src/Newtonsoft.Json/JsonConverter.cs
index bff625b..849f9be 100644
--- a/Src/Newtonsoft.Json/JsonConverter.cs
+++ b/Src/Newtonsoft.Json/JsonConverter.cs
@@ -40,9 +40,9 @@ namespace Newtonsoft.Json
public virtual object ReadJson(JsonReader reader, Type objectType)
{
- throw new NotImplementedException(string.Format("{0} has not overriden FromJson method.", GetType().Name));
+ throw new NotImplementedException(string.Format("{0} has not overriden the ReadJson method.", GetType().Name));
}
public abstract bool CanConvert(Type objectType);
}
-}
+} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs
index db7181e..8421c2d 100644
--- a/Src/Newtonsoft.Json/JsonReader.cs
+++ b/Src/Newtonsoft.Json/JsonReader.cs
@@ -217,11 +217,54 @@ namespace Newtonsoft.Json
ClearCurrentChar();
_currentState = State.PostValue;
- _token = JsonToken.String;
- _value = _buffer.ToString();
+ string text = _buffer.ToString();
_buffer.Position = 0;
- _valueType = typeof(string);
- _quoteChar = quote;
+
+ if (text.StartsWith("/Date(", StringComparison.Ordinal) && text.EndsWith(")/", StringComparison.Ordinal))
+ {
+ ParseDate(text);
+ }
+ else
+ {
+ SetToken(JsonToken.String, text);
+ _quoteChar = quote;
+ }
+ }
+
+ private void ParseDate(string text)
+ {
+ string value = text.Substring(6, text.Length - 8);
+ DateTimeKind kind = DateTimeKind.Utc;
+
+ int index = value.IndexOf('+', 1);
+
+ if (index == -1)
+ index = value.IndexOf('-', 1);
+
+ if (index != -1)
+ {
+ kind = DateTimeKind.Local;
+ value = value.Substring(0, index);
+ }
+
+ long javaScriptTicks = long.Parse(value);
+ DateTime utcDateTime = JavaScriptConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
+ DateTime dateTime;
+
+ switch (kind)
+ {
+ case DateTimeKind.Unspecified:
+ dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
+ break;
+ case DateTimeKind.Local:
+ dateTime = utcDateTime.ToLocalTime();
+ break;
+ default:
+ dateTime = utcDateTime;
+ break;
+ }
+
+ SetToken(JsonToken.Date, dateTime);
}
private bool MoveNext()
@@ -648,22 +691,22 @@ namespace Newtonsoft.Json
_value = constructorName;
_valueType = typeof(string);
- if (string.CompareOrdinal(constructorName, "Date") == 0)
- {
- IList<object> parameters = new List<object>();
+ //if (string.CompareOrdinal(constructorName, "Date") == 0)
+ //{
+ // IList<object> parameters = new List<object>();
- MoveNext();
- while (ParseValue() && _token != JsonToken.EndConstructor)
- {
- parameters.Add(_value);
- }
+ // MoveNext();
+ // while (ParseValue() && _token != JsonToken.EndConstructor)
+ // {
+ // parameters.Add(_value);
+ // }
- long javaScriptTicks = Convert.ToInt64(parameters[0]);
+ // long javaScriptTicks = Convert.ToInt64(parameters[0]);
- DateTime date = JavaScriptConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
+ // DateTime date = JavaScriptConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
- SetToken(JsonToken.Date, date);
- }
+ // SetToken(JsonToken.Date, date);
+ //}
@@ -754,6 +797,9 @@ namespace Newtonsoft.Json
case JsonType.Array:
_currentState = State.Array;
break;
+ case JsonType.Constructor:
+ _currentState = State.Constructor;
+ break;
case JsonType.None:
_currentState = State.Finished;
break;
diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs
index 55243ed..359ed71 100644
--- a/Src/Newtonsoft.Json/JsonSerializer.cs
+++ b/Src/Newtonsoft.Json/JsonSerializer.cs
@@ -32,6 +32,7 @@ using System.Reflection;
using System.ComponentModel;
using Newtonsoft.Json.Utilities;
using System.Globalization;
+using System.Linq;
namespace Newtonsoft.Json
{
@@ -233,11 +234,7 @@ namespace Newtonsoft.Json
case JsonToken.EndConstructor:
string constructorName = reader.Value.ToString();
- //if (string.CompareOrdinal(constructorName, "Date") == 0)
- // value = CreateDate(reader);
- //else
- //TODO: use objectType plus constructor arguments to instantiate object
- value = constructorName;
+ value = constructorName;
break;
case JsonToken.Null:
case JsonToken.Undefined:
@@ -298,12 +295,15 @@ namespace Newtonsoft.Json
return targetConverter.ConvertFromInvariantString(valueString);
}
+ if (targetType == typeof(DateTimeOffset) && value is DateTime)
+ return new DateTimeOffset((DateTime)value);
+
if (!targetType.IsAssignableFrom(valueType))
throw new InvalidOperationException(string.Format("Cannot convert object of type '{0}' to type '{1}'", value.GetType(), targetType));
return value;
}
-
+
return targetConverter.ConvertFrom(null, CultureInfo.InvariantCulture, value);
}
else
@@ -343,7 +343,7 @@ namespace Newtonsoft.Json
else
mappedName = member.Name;
- bool ignored = member.IsDefined(typeof (JsonIgnoreAttribute), true);
+ bool ignored = member.IsDefined(typeof(JsonIgnoreAttribute), true);
bool readable = ReflectionUtils.CanReadMemberValue(member);
bool writable = ReflectionUtils.CanSetMemberValue(member);
MemberMapping memberMapping = new MemberMapping(mappedName, member, ignored, readable, writable);
@@ -409,50 +409,102 @@ namespace Newtonsoft.Json
Type elementType = ReflectionUtils.GetListItemType(objectType);
IList populatedList = CollectionUtils.CreateAndPopulateList(objectType, delegate(IList list)
+ {
+ while (reader.Read())
{
- while (reader.Read())
+ switch (reader.TokenType)
{
- switch (reader.TokenType)
- {
- case JsonToken.EndArray:
- return;
- case JsonToken.Comment:
- break;
- default:
- object value = GetObject(reader, elementType);
-
- list.Add(value);
- break;
- }
+ case JsonToken.EndArray:
+ return;
+ case JsonToken.Comment:
+ break;
+ default:
+ object value = GetObject(reader, elementType);
+
+ list.Add(value);
+ break;
}
+ }
- throw new JsonSerializationException("Unexpected end when deserializing array.");
- });
+ throw new JsonSerializationException("Unexpected end when deserializing array.");
+ });
return populatedList;
}
private object PopulateObject(JsonReader reader, Type objectType)
{
- object newObject = Activator.CreateInstance(objectType);
+ object newObject;
- while (reader.Read())
+ if (ReflectionUtils.HasDefaultConstructor(objectType))
{
- switch (reader.TokenType)
+ newObject = Activator.CreateInstance(objectType);
+
+ while (reader.Read())
{
- case JsonToken.PropertyName:
- string memberName = reader.Value.ToString();
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ string memberName = reader.Value.ToString();
- SetObjectMember(reader, newObject, objectType, memberName);
- break;
- case JsonToken.EndObject:
- return newObject;
- default:
- throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType);
+ SetObjectMember(reader, newObject, objectType, memberName);
+ break;
+ case JsonToken.EndObject:
+ return newObject;
+ default:
+ throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType);
+ }
}
+
+ throw new JsonSerializationException("Unexpected end when deserializing object.");
}
+ else
+ {
+ ConstructorInfo c = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).SingleOrDefault();
+
+ if (c == null)
+ throw new Exception("sdsdf");
+
+ IDictionary<ParameterInfo, object> constructorParameters = c.GetParameters().ToDictionary(p => p, p => (object)null);
+ //IList<object> constructorValues
+
+ bool exit = false;
+ while (!exit && reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ string memberName = reader.Value.ToString();
+ ParameterInfo matchingConstructorParameter = constructorParameters
+ .Where(kv => kv.Key.Name == memberName)
+ .Select(kv => kv.Key)
+ .SingleOrDefault();
+
+ if (!reader.Read())
+ throw new JsonSerializationException(string.Format("Unexpected end when setting {0}'s value.", memberName));
+
+
+ if (matchingConstructorParameter != null)
+ {
+ constructorParameters[matchingConstructorParameter] = GetObject(reader, matchingConstructorParameter.ParameterType);
+ }
+
- throw new JsonSerializationException("Unexpected end when deserializing object.");
+
+ //SetObjectMember(reader, newObject, objectType, memberName);
+ break;
+ case JsonToken.EndObject:
+ exit = true;
+ break;
+ default:
+ throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType);
+ }
+ }
+
+ newObject = Activator.CreateInstance(objectType, constructorParameters.Values.ToArray());
+
+ return newObject;
+ }
}
#endregion
@@ -554,6 +606,10 @@ namespace Newtonsoft.Json
break;
}
}
+ else if (value is DateTimeOffset)
+ {
+ writer.WriteValue((DateTimeOffset)value);
+ }
else if (value is IList)
{
SerializeList(writer, (IList)value);
@@ -694,4 +750,4 @@ namespace Newtonsoft.Json
}
#endregion
}
-}
+} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs
index 953f198..f488e6b 100644
--- a/Src/Newtonsoft.Json/JsonWriter.cs
+++ b/Src/Newtonsoft.Json/JsonWriter.cs
@@ -724,6 +724,15 @@ namespace Newtonsoft.Json
{
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Date);
}
+
+ /// <summary>
+ /// Writes a <see cref="DateTimeOffset"/> value.
+ /// </summary>
+ /// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
+ public void WriteValue(DateTimeOffset value)
+ {
+ WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Date);
+ }
#endregion
/// <summary>
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
index 51fb364..530039e 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
@@ -73,7 +73,9 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="Converters\AspNetAjaxDateTimeConverter.cs" />
+ <Compile Include="Converters\IsoDateTimeConverter.cs" />
+ <Compile Include="Converters\JavaScriptDateTimeConverter.cs" />
+ <Compile Include="Converters\JsonDateTimeSerializationMode.cs" />
<Compile Include="Converters\XmlNodeConverter.cs" />
<Compile Include="Converters\HtmlColorConverter.cs" />
<Compile Include="JavaScriptParameters.cs" />
@@ -105,6 +107,7 @@
<Compile Include="MissingMemberHandling.cs" />
<Compile Include="NullValueHandling.cs" />
<Compile Include="ReferenceLoopHandling.cs" />
+ <Compile Include="Utilities\DateTimeUtils.cs" />
<Compile Include="Utilities\JavaScriptUtils.cs" />
<Compile Include="JsonToken.cs" />
<Compile Include="JsonWriter.cs" />
diff --git a/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs b/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs
new file mode 100644
index 0000000..4ba824a
--- /dev/null
+++ b/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml;
+
+namespace Newtonsoft.Json.Utilities
+{
+ public static class DateTimeUtils
+ {
+ public static string GetLocalOffset(this DateTime d)
+ {
+ TimeSpan utcOffset = TimeZoneInfo.Local.GetUtcOffset(d);
+
+ return utcOffset.Hours.ToString("+00;-00") + ":" + utcOffset.Minutes.ToString("00;00");
+ }
+
+ public static XmlDateTimeSerializationMode ToSerializationMode(DateTimeKind kind)
+ {
+ switch (kind)
+ {
+ case DateTimeKind.Local:
+ return XmlDateTimeSerializationMode.Local;
+ case DateTimeKind.Unspecified:
+ return XmlDateTimeSerializationMode.Unspecified;
+ case DateTimeKind.Utc:
+ return XmlDateTimeSerializationMode.Utc;
+ default:
+ throw new ArgumentOutOfRangeException("kind", kind, "Unexpected DateTimeKind value.");
+ }
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs
index c6084c3..79a2170 100644
--- a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs
+++ b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs
@@ -545,4 +545,4 @@ namespace Newtonsoft.Json.Utilities
return Activator.CreateInstance(specificType, args);
}
}
-}
+} \ No newline at end of file