#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.IO; using System.Runtime.Serialization; using System.Text; #if !(NET20 || NET35 || SILVERLIGHT) using System.Threading.Tasks; #endif using System.Xml; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Tests.Serialization; using Newtonsoft.Json.Tests.TestObjects; using Newtonsoft.Json.Utilities; #if !NETFX_CORE using NUnit.Framework; #else using Microsoft.VisualStudio.TestTools.UnitTesting; using TestFixture = Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute; using Test = Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute; #endif namespace Newtonsoft.Json.Tests { [TestFixture] public class JsonConvertTest : TestFixtureBase { #if Entities [Test] public void EntitiesTest() { Purchase purchase = new Purchase() { Id = 1 }; purchase.PurchaseLine.Add(new PurchaseLine() { Id = 1, Purchase = purchase }); purchase.PurchaseLine.Add(new PurchaseLine() { Id = 2, Purchase = purchase }); StringWriter sw = new StringWriter(); JsonSerializer serializer = new JsonSerializer(); serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; using (JsonWriter jw = new JsonTextWriter(sw)) { jw.Formatting = Formatting.Indented; serializer.Serialize(jw, purchase); } string json = sw.ToString(); Assert.AreEqual(@"{ ""Id"": 1, ""PurchaseLine"": [ { ""Id"": 1, ""PurchaseReference"": { ""EntityKey"": null, ""RelationshipName"": ""EntityDataModel.PurchasePurchaseLine"", ""SourceRoleName"": ""PurchaseLine"", ""TargetRoleName"": ""Purchase"", ""RelationshipSet"": null, ""IsLoaded"": false }, ""EntityState"": 1, ""EntityKey"": null }, { ""Id"": 2, ""PurchaseReference"": { ""EntityKey"": null, ""RelationshipName"": ""EntityDataModel.PurchasePurchaseLine"", ""SourceRoleName"": ""PurchaseLine"", ""TargetRoleName"": ""Purchase"", ""RelationshipSet"": null, ""IsLoaded"": false }, ""EntityState"": 1, ""EntityKey"": null } ], ""EntityState"": 1, ""EntityKey"": null }", json); Purchase newPurchase = JsonConvert.DeserializeObject(json); Assert.AreEqual(1, newPurchase.Id); Assert.AreEqual(2, newPurchase.PurchaseLine.Count); Assert.AreEqual(1, newPurchase.PurchaseLine.ElementAt(0).Id); Assert.AreEqual(2, newPurchase.PurchaseLine.ElementAt(1).Id); } #endif [Test] public void EscapeJavaScriptString() { string result; result = JavaScriptUtils.ToEscapedJavaScriptString("How now brown cow?", '"', true); Assert.AreEqual(@"""How now brown cow?""", result); result = JavaScriptUtils.ToEscapedJavaScriptString("How now 'brown' cow?", '"', true); Assert.AreEqual(@"""How now 'brown' cow?""", result); result = JavaScriptUtils.ToEscapedJavaScriptString("How now cow?", '"', true); Assert.AreEqual(@"""How now cow?""", result); result = JavaScriptUtils.ToEscapedJavaScriptString(@"How now brown cow?", '"', true); Assert.AreEqual(@"""How \r\nnow brown cow?""", result); result = JavaScriptUtils.ToEscapedJavaScriptString("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007", '"', true); Assert.AreEqual(@"""\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007""", result); result = JavaScriptUtils.ToEscapedJavaScriptString("\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013", '"', true); Assert.AreEqual(@"""\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013""", result); result = JavaScriptUtils.ToEscapedJavaScriptString( "\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f ", '"', true); Assert.AreEqual(@"""\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f """, result); result = JavaScriptUtils.ToEscapedJavaScriptString( "!\"#$%&\u0027()*+,-./0123456789:;\u003c=\u003e?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]", '"', true); Assert.AreEqual(@"""!\""#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]""", result); result = JavaScriptUtils.ToEscapedJavaScriptString("^_`abcdefghijklmnopqrstuvwxyz{|}~", '"', true); Assert.AreEqual(@"""^_`abcdefghijklmnopqrstuvwxyz{|}~""", result); string data = "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&\u0027()*+,-./0123456789:;\u003c=\u003e?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; string expected = @"""\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\""#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"""; result = JavaScriptUtils.ToEscapedJavaScriptString(data, '"', true); Assert.AreEqual(expected, result); result = JavaScriptUtils.ToEscapedJavaScriptString("Fred's cat.", '\'', true); Assert.AreEqual(result, @"'Fred\'s cat.'"); result = JavaScriptUtils.ToEscapedJavaScriptString(@"""How are you gentlemen?"" said Cats.", '"', true); Assert.AreEqual(result, @"""\""How are you gentlemen?\"" said Cats."""); result = JavaScriptUtils.ToEscapedJavaScriptString(@"""How are' you gentlemen?"" said Cats.", '"', true); Assert.AreEqual(result, @"""\""How are' you gentlemen?\"" said Cats."""); result = JavaScriptUtils.ToEscapedJavaScriptString(@"Fred's ""cat"".", '\'', true); Assert.AreEqual(result, @"'Fred\'s ""cat"".'"); result = JavaScriptUtils.ToEscapedJavaScriptString("\u001farray\u003caddress"); Assert.AreEqual(result, @"""\u001farray("Unsupported type: System.Version. Use the JsonSerializer class to get the object's JSON representation.", () => { JsonConvert.ToString(new Version(1, 0)); }); } [Test] public void GuidToString() { Guid guid = new Guid("BED7F4EA-1A96-11d2-8F08-00A0C9A6186D"); string json = JsonConvert.ToString(guid); Assert.AreEqual(@"""bed7f4ea-1a96-11d2-8f08-00a0c9a6186d""", json); } [Test] public void EnumToString() { string json = JsonConvert.ToString(StringComparison.CurrentCultureIgnoreCase); Assert.AreEqual("1", json); } [Test] public void ObjectToString() { object value; value = 1; Assert.AreEqual("1", JsonConvert.ToString(value)); value = 1.1; Assert.AreEqual("1.1", JsonConvert.ToString(value)); value = 1.1m; Assert.AreEqual("1.1", JsonConvert.ToString(value)); value = (float)1.1; Assert.AreEqual("1.1", JsonConvert.ToString(value)); value = (short)1; Assert.AreEqual("1", JsonConvert.ToString(value)); value = (long)1; Assert.AreEqual("1", JsonConvert.ToString(value)); value = (byte)1; Assert.AreEqual("1", JsonConvert.ToString(value)); value = (uint)1; Assert.AreEqual("1", JsonConvert.ToString(value)); value = (ushort)1; Assert.AreEqual("1", JsonConvert.ToString(value)); value = (sbyte)1; Assert.AreEqual("1", JsonConvert.ToString(value)); value = (ulong)1; Assert.AreEqual("1", JsonConvert.ToString(value)); value = new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc); Assert.AreEqual(@"""1970-01-01T00:00:00Z""", JsonConvert.ToString(value)); value = new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc); Assert.AreEqual(@"""\/Date(0)\/""", JsonConvert.ToString((DateTime)value, DateFormatHandling.MicrosoftDateFormat, DateTimeZoneHandling.RoundtripKind)); #if !PocketPC && !NET20 value = new DateTimeOffset(JsonConvert.InitialJavaScriptDateTicks, TimeSpan.Zero); Assert.AreEqual(@"""1970-01-01T00:00:00+00:00""", JsonConvert.ToString(value)); value = new DateTimeOffset(JsonConvert.InitialJavaScriptDateTicks, TimeSpan.Zero); Assert.AreEqual(@"""\/Date(0+0000)\/""", JsonConvert.ToString((DateTimeOffset)value, DateFormatHandling.MicrosoftDateFormat)); #endif value = null; Assert.AreEqual("null", JsonConvert.ToString(value)); #if !NETFX_CORE value = DBNull.Value; Assert.AreEqual("null", JsonConvert.ToString(value)); #endif value = "I am a string"; Assert.AreEqual(@"""I am a string""", JsonConvert.ToString(value)); value = true; Assert.AreEqual("true", JsonConvert.ToString(value)); value = 'c'; Assert.AreEqual(@"""c""", JsonConvert.ToString(value)); } [Test] public void TestInvalidStrings() { ExceptionAssert.Throws("Additional text encountered after finished reading JSON content: t. Line 1, position 19.", () => { string orig = @"this is a string ""that has quotes"" "; string serialized = JsonConvert.SerializeObject(orig); // *** Make string invalid by stripping \" \" serialized = serialized.Replace(@"\""", "\""); JsonConvert.DeserializeObject(serialized); }); } [Test] public void DeserializeValueObjects() { int i = JsonConvert.DeserializeObject("1"); Assert.AreEqual(1, i); #if !PocketPC && !NET20 DateTimeOffset d = JsonConvert.DeserializeObject(@"""\/Date(-59011455539000+0000)\/"""); Assert.AreEqual(new DateTimeOffset(new DateTime(100, 1, 1, 1, 1, 1, DateTimeKind.Utc)), d); #endif bool b = JsonConvert.DeserializeObject("true"); Assert.AreEqual(true, b); object n = JsonConvert.DeserializeObject("null"); Assert.AreEqual(null, n); object u = JsonConvert.DeserializeObject("undefined"); Assert.AreEqual(null, u); } [Test] public void FloatToString() { Assert.AreEqual("1.1", JsonConvert.ToString(1.1)); Assert.AreEqual("1.11", JsonConvert.ToString(1.11)); Assert.AreEqual("1.111", JsonConvert.ToString(1.111)); Assert.AreEqual("1.1111", JsonConvert.ToString(1.1111)); Assert.AreEqual("1.11111", JsonConvert.ToString(1.11111)); Assert.AreEqual("1.111111", JsonConvert.ToString(1.111111)); Assert.AreEqual("1.0", JsonConvert.ToString(1.0)); Assert.AreEqual("1.0", JsonConvert.ToString(1d)); Assert.AreEqual("-1.0", JsonConvert.ToString(-1d)); Assert.AreEqual("1.01", JsonConvert.ToString(1.01)); Assert.AreEqual("1.001", JsonConvert.ToString(1.001)); Assert.AreEqual(JsonConvert.PositiveInfinity, JsonConvert.ToString(Double.PositiveInfinity)); Assert.AreEqual(JsonConvert.NegativeInfinity, JsonConvert.ToString(Double.NegativeInfinity)); Assert.AreEqual(JsonConvert.NaN, JsonConvert.ToString(Double.NaN)); } [Test] public void DecimalToString() { Assert.AreEqual("1.1", JsonConvert.ToString(1.1m)); Assert.AreEqual("1.11", JsonConvert.ToString(1.11m)); Assert.AreEqual("1.111", JsonConvert.ToString(1.111m)); Assert.AreEqual("1.1111", JsonConvert.ToString(1.1111m)); Assert.AreEqual("1.11111", JsonConvert.ToString(1.11111m)); Assert.AreEqual("1.111111", JsonConvert.ToString(1.111111m)); Assert.AreEqual("1.0", JsonConvert.ToString(1.0m)); Assert.AreEqual("-1.0", JsonConvert.ToString(-1.0m)); Assert.AreEqual("-1.0", JsonConvert.ToString(-1m)); Assert.AreEqual("1.0", JsonConvert.ToString(1m)); Assert.AreEqual("1.01", JsonConvert.ToString(1.01m)); Assert.AreEqual("1.001", JsonConvert.ToString(1.001m)); Assert.AreEqual("79228162514264337593543950335.0", JsonConvert.ToString(Decimal.MaxValue)); Assert.AreEqual("-79228162514264337593543950335.0", JsonConvert.ToString(Decimal.MinValue)); } [Test] public void StringEscaping() { string v = @"It's a good day ""sunshine"""; string json = JsonConvert.ToString(v); Assert.AreEqual(@"""It's a good day\r\n\""sunshine\""""", json); } [Test] public void WriteDateTime() { DateTimeResult result = null; result = TestDateTime("DateTime Max", DateTime.MaxValue); Assert.AreEqual("9999-12-31T23:59:59.9999999", result.IsoDateRoundtrip); Assert.AreEqual("9999-12-31T23:59:59.9999999" + GetOffset(DateTime.MaxValue, DateFormatHandling.IsoDateFormat), result.IsoDateLocal); Assert.AreEqual("9999-12-31T23:59:59.9999999", result.IsoDateUnspecified); Assert.AreEqual("9999-12-31T23:59:59.9999999Z", result.IsoDateUtc); Assert.AreEqual(@"\/Date(253402300799999)\/", result.MsDateRoundtrip); Assert.AreEqual(@"\/Date(253402300799999" + GetOffset(DateTime.MaxValue, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateLocal); Assert.AreEqual(@"\/Date(253402300799999)\/", result.MsDateUnspecified); Assert.AreEqual(@"\/Date(253402300799999)\/", result.MsDateUtc); DateTime year2000local = new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Local); string localToUtcDate = year2000local.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.FFFFFFFK"); result = TestDateTime("DateTime Local", year2000local); Assert.AreEqual("2000-01-01T01:01:01" + GetOffset(year2000local, DateFormatHandling.IsoDateFormat), result.IsoDateRoundtrip); Assert.AreEqual("2000-01-01T01:01:01" + GetOffset(year2000local, DateFormatHandling.IsoDateFormat), result.IsoDateLocal); Assert.AreEqual("2000-01-01T01:01:01", result.IsoDateUnspecified); Assert.AreEqual(localToUtcDate, result.IsoDateUtc); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(year2000local) + GetOffset(year2000local, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateRoundtrip); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(year2000local) + GetOffset(year2000local, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateLocal); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(year2000local) + GetOffset(year2000local, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateUnspecified); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(year2000local) + @")\/", result.MsDateUtc); DateTime millisecondsLocal = new DateTime(2000, 1, 1, 1, 1, 1, 999, DateTimeKind.Local); localToUtcDate = millisecondsLocal.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.FFFFFFFK"); result = TestDateTime("DateTime Local with milliseconds", millisecondsLocal); Assert.AreEqual("2000-01-01T01:01:01.999" + GetOffset(millisecondsLocal, DateFormatHandling.IsoDateFormat), result.IsoDateRoundtrip); Assert.AreEqual("2000-01-01T01:01:01.999" + GetOffset(millisecondsLocal, DateFormatHandling.IsoDateFormat), result.IsoDateLocal); Assert.AreEqual("2000-01-01T01:01:01.999", result.IsoDateUnspecified); Assert.AreEqual(localToUtcDate, result.IsoDateUtc); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(millisecondsLocal) + GetOffset(millisecondsLocal, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateRoundtrip); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(millisecondsLocal) + GetOffset(millisecondsLocal, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateLocal); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(millisecondsLocal) + GetOffset(millisecondsLocal, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateUnspecified); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(millisecondsLocal) + @")\/", result.MsDateUtc); DateTime ticksLocal = new DateTime(634663873826822481, DateTimeKind.Local); localToUtcDate = ticksLocal.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.FFFFFFFK"); result = TestDateTime("DateTime Local with ticks", ticksLocal); Assert.AreEqual("2012-03-03T16:03:02.6822481" + GetOffset(ticksLocal, DateFormatHandling.IsoDateFormat), result.IsoDateRoundtrip); Assert.AreEqual("2012-03-03T16:03:02.6822481" + GetOffset(ticksLocal, DateFormatHandling.IsoDateFormat), result.IsoDateLocal); Assert.AreEqual("2012-03-03T16:03:02.6822481", result.IsoDateUnspecified); Assert.AreEqual(localToUtcDate, result.IsoDateUtc); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(ticksLocal) + GetOffset(ticksLocal, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateRoundtrip); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(ticksLocal) + GetOffset(ticksLocal, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateLocal); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(ticksLocal) + GetOffset(ticksLocal, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateUnspecified); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(ticksLocal) + @")\/", result.MsDateUtc); DateTime year2000Unspecified = new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Unspecified); result = TestDateTime("DateTime Unspecified", year2000Unspecified); Assert.AreEqual("2000-01-01T01:01:01", result.IsoDateRoundtrip); Assert.AreEqual("2000-01-01T01:01:01" + GetOffset(year2000Unspecified, DateFormatHandling.IsoDateFormat), result.IsoDateLocal); Assert.AreEqual("2000-01-01T01:01:01", result.IsoDateUnspecified); Assert.AreEqual("2000-01-01T01:01:01Z", result.IsoDateUtc); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(year2000Unspecified) + GetOffset(year2000Unspecified, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateRoundtrip); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(year2000Unspecified) + GetOffset(year2000Unspecified, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateLocal); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(year2000Unspecified) + GetOffset(year2000Unspecified, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateUnspecified); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(year2000Unspecified.ToLocalTime()) + @")\/", result.MsDateUtc); DateTime year2000Utc = new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc); string utcTolocalDate = year2000Utc.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ss"); result = TestDateTime("DateTime Utc", year2000Utc); Assert.AreEqual("2000-01-01T01:01:01Z", result.IsoDateRoundtrip); Assert.AreEqual(utcTolocalDate + GetOffset(year2000Utc, DateFormatHandling.IsoDateFormat), result.IsoDateLocal); Assert.AreEqual("2000-01-01T01:01:01", result.IsoDateUnspecified); Assert.AreEqual("2000-01-01T01:01:01Z", result.IsoDateUtc); Assert.AreEqual(@"\/Date(946688461000)\/", result.MsDateRoundtrip); Assert.AreEqual(@"\/Date(946688461000" + GetOffset(year2000Utc, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateLocal); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(DateTime.SpecifyKind(year2000Utc, DateTimeKind.Unspecified)) + GetOffset(year2000Utc, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateUnspecified); Assert.AreEqual(@"\/Date(946688461000)\/", result.MsDateUtc); DateTime unixEpoc = new DateTime(621355968000000000, DateTimeKind.Utc); utcTolocalDate = unixEpoc.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ss"); result = TestDateTime("DateTime Unix Epoc", unixEpoc); Assert.AreEqual("1970-01-01T00:00:00Z", result.IsoDateRoundtrip); Assert.AreEqual(utcTolocalDate + GetOffset(unixEpoc, DateFormatHandling.IsoDateFormat), result.IsoDateLocal); Assert.AreEqual("1970-01-01T00:00:00", result.IsoDateUnspecified); Assert.AreEqual("1970-01-01T00:00:00Z", result.IsoDateUtc); Assert.AreEqual(@"\/Date(0)\/", result.MsDateRoundtrip); Assert.AreEqual(@"\/Date(0" + GetOffset(unixEpoc, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateLocal); Assert.AreEqual(@"\/Date(" + JsonConvert.ConvertDateTimeToJavaScriptTicks(DateTime.SpecifyKind(unixEpoc, DateTimeKind.Unspecified)) + GetOffset(unixEpoc, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateUnspecified); Assert.AreEqual(@"\/Date(0)\/", result.MsDateUtc); result = TestDateTime("DateTime Min", DateTime.MinValue); Assert.AreEqual("0001-01-01T00:00:00", result.IsoDateRoundtrip); Assert.AreEqual("0001-01-01T00:00:00" + GetOffset(DateTime.MinValue, DateFormatHandling.IsoDateFormat), result.IsoDateLocal); Assert.AreEqual("0001-01-01T00:00:00", result.IsoDateUnspecified); Assert.AreEqual("0001-01-01T00:00:00Z", result.IsoDateUtc); Assert.AreEqual(@"\/Date(-62135596800000)\/", result.MsDateRoundtrip); Assert.AreEqual(@"\/Date(-62135596800000" + GetOffset(DateTime.MinValue, DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateLocal); Assert.AreEqual(@"\/Date(-62135596800000)\/", result.MsDateUnspecified); Assert.AreEqual(@"\/Date(-62135596800000)\/", result.MsDateUtc); result = TestDateTime("DateTime Default", default(DateTime)); Assert.AreEqual("0001-01-01T00:00:00", result.IsoDateRoundtrip); Assert.AreEqual("0001-01-01T00:00:00" + GetOffset(default(DateTime), DateFormatHandling.IsoDateFormat), result.IsoDateLocal); Assert.AreEqual("0001-01-01T00:00:00", result.IsoDateUnspecified); Assert.AreEqual("0001-01-01T00:00:00Z", result.IsoDateUtc); Assert.AreEqual(@"\/Date(-62135596800000)\/", result.MsDateRoundtrip); Assert.AreEqual(@"\/Date(-62135596800000" + GetOffset(default(DateTime), DateFormatHandling.MicrosoftDateFormat) + @")\/", result.MsDateLocal); Assert.AreEqual(@"\/Date(-62135596800000)\/", result.MsDateUnspecified); Assert.AreEqual(@"\/Date(-62135596800000)\/", result.MsDateUtc); #if !NET20 result = TestDateTime("DateTimeOffset TimeSpan Zero", new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.Zero)); Assert.AreEqual("2000-01-01T01:01:01+00:00", result.IsoDateRoundtrip); Assert.AreEqual(@"\/Date(946688461000+0000)\/", result.MsDateRoundtrip); result = TestDateTime("DateTimeOffset TimeSpan 1 hour", new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.FromHours(1))); Assert.AreEqual("2000-01-01T01:01:01+01:00", result.IsoDateRoundtrip); Assert.AreEqual(@"\/Date(946684861000+0100)\/", result.MsDateRoundtrip); result = TestDateTime("DateTimeOffset TimeSpan 1.5 hour", new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.FromHours(1.5))); Assert.AreEqual("2000-01-01T01:01:01+01:30", result.IsoDateRoundtrip); Assert.AreEqual(@"\/Date(946683061000+0130)\/", result.MsDateRoundtrip); result = TestDateTime("DateTimeOffset TimeSpan 13 hour", new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.FromHours(13))); Assert.AreEqual("2000-01-01T01:01:01+13:00", result.IsoDateRoundtrip); Assert.AreEqual(@"\/Date(946641661000+1300)\/", result.MsDateRoundtrip); result = TestDateTime("DateTimeOffset TimeSpan with ticks", new DateTimeOffset(634663873826822481, TimeSpan.Zero)); Assert.AreEqual("2012-03-03T16:03:02.6822481+00:00", result.IsoDateRoundtrip); Assert.AreEqual(@"\/Date(1330790582682+0000)\/", result.MsDateRoundtrip); result = TestDateTime("DateTimeOffset Min", DateTimeOffset.MinValue); Assert.AreEqual("0001-01-01T00:00:00+00:00", result.IsoDateRoundtrip); Assert.AreEqual(@"\/Date(-62135596800000+0000)\/", result.MsDateRoundtrip); result = TestDateTime("DateTimeOffset Max", DateTimeOffset.MaxValue); Assert.AreEqual("9999-12-31T23:59:59.9999999+00:00", result.IsoDateRoundtrip); Assert.AreEqual(@"\/Date(253402300799999+0000)\/", result.MsDateRoundtrip); result = TestDateTime("DateTimeOffset Default", default(DateTimeOffset)); Assert.AreEqual("0001-01-01T00:00:00+00:00", result.IsoDateRoundtrip); Assert.AreEqual(@"\/Date(-62135596800000+0000)\/", result.MsDateRoundtrip); #endif } public class DateTimeResult { public string IsoDateRoundtrip { get; set; } public string IsoDateLocal { get; set; } public string IsoDateUnspecified { get; set; } public string IsoDateUtc { get; set; } public string MsDateRoundtrip { get; set; } public string MsDateLocal { get; set; } public string MsDateUnspecified { get; set; } public string MsDateUtc { get; set; } } private DateTimeResult TestDateTime(string name, T value) { Console.WriteLine(name); DateTimeResult result = new DateTimeResult(); result.IsoDateRoundtrip = TestDateTimeFormat(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); if (value is DateTime) { result.IsoDateLocal = TestDateTimeFormat(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.Local); result.IsoDateUnspecified = TestDateTimeFormat(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.Unspecified); result.IsoDateUtc = TestDateTimeFormat(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.Utc); } result.MsDateRoundtrip = TestDateTimeFormat(value, DateFormatHandling.MicrosoftDateFormat, DateTimeZoneHandling.RoundtripKind); if (value is DateTime) { result.MsDateLocal = TestDateTimeFormat(value, DateFormatHandling.MicrosoftDateFormat, DateTimeZoneHandling.Local); result.MsDateUnspecified = TestDateTimeFormat(value, DateFormatHandling.MicrosoftDateFormat, DateTimeZoneHandling.Unspecified); result.MsDateUtc = TestDateTimeFormat(value, DateFormatHandling.MicrosoftDateFormat, DateTimeZoneHandling.Utc); } TestDateTimeFormat(value, new IsoDateTimeConverter()); #if !NETFX_CORE if (value is DateTime) { Console.WriteLine(XmlConvert.ToString((DateTime)(object)value, XmlDateTimeSerializationMode.RoundtripKind)); } else { Console.WriteLine(XmlConvert.ToString((DateTimeOffset)(object)value)); } #endif #if !NET20 MemoryStream ms = new MemoryStream(); DataContractSerializer s = new DataContractSerializer(typeof(T)); s.WriteObject(ms, value); string json = Encoding.UTF8.GetString(ms.ToArray(), 0, Convert.ToInt32(ms.Length)); Console.WriteLine(json); #endif Console.WriteLine(); return result; } private static string TestDateTimeFormat(T value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) { string date = null; if (value is DateTime) { date = JsonConvert.ToString((DateTime)(object)value, format, timeZoneHandling); } else { #if !NET20 date = JsonConvert.ToString((DateTimeOffset)(object)value, format); #endif } Console.WriteLine(format.ToString("g") + "-" + timeZoneHandling.ToString("g") + ": " + date); if (timeZoneHandling == DateTimeZoneHandling.RoundtripKind) { T parsed = JsonConvert.DeserializeObject(date); try { Assert.AreEqual(value, parsed); } catch (Exception ex) { long valueTicks = GetTicks(value); long parsedTicks = GetTicks(parsed); valueTicks = (valueTicks/10000)*10000; Assert.AreEqual(valueTicks, parsedTicks); } } return date.Trim('"'); } private static void TestDateTimeFormat(T value, JsonConverter converter) { string date = Write(value, converter); Console.WriteLine(converter.GetType().Name + ": " + date); T parsed = Read(date, converter); try { Assert.AreEqual(value, parsed); } catch (Exception ex) { // JavaScript ticks aren't as precise, recheck after rounding long valueTicks = GetTicks(value); long parsedTicks = GetTicks(parsed); valueTicks = (valueTicks / 10000) * 10000; Assert.AreEqual(valueTicks, parsedTicks); } } public static long GetTicks(object value) { return (value is DateTime) ? ((DateTime)value).Ticks : ((DateTimeOffset)value).Ticks; } public static string Write(object value, JsonConverter converter) { StringWriter sw = new StringWriter(); JsonTextWriter writer = new JsonTextWriter(sw); converter.WriteJson(writer, value, null); writer.Flush(); return sw.ToString(); } public static T Read(string text, JsonConverter converter) { JsonTextReader reader = new JsonTextReader(new StringReader(text)); reader.ReadAsString(); return (T)converter.ReadJson(reader, typeof(T), null, null); } #if !(NET20 || NET35 || SILVERLIGHT) [Test] public void Async() { Task task = null; task = JsonConvert.SerializeObjectAsync(42); task.Wait(); Assert.AreEqual("42", task.Result); task = JsonConvert.SerializeObjectAsync(new[] {1, 2, 3, 4, 5}, Formatting.Indented); task.Wait(); Assert.AreEqual(@"[ 1, 2, 3, 4, 5 ]", task.Result); task = JsonConvert.SerializeObjectAsync(DateTime.MaxValue, Formatting.None, new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat }); task.Wait(); Assert.AreEqual(@"""\/Date(253402300799999)\/""", task.Result); var taskObject = JsonConvert.DeserializeObjectAsync("[]"); taskObject.Wait(); CollectionAssert.AreEquivalent(new JArray(), (JArray)taskObject.Result); Task taskVersionArray = JsonConvert.DeserializeObjectAsync("['2.0']", typeof(Version[]), new JsonSerializerSettings { Converters = {new VersionConverter()} }); taskVersionArray.Wait(); Version[] versionArray = (Version[])taskVersionArray.Result; Assert.AreEqual(1, versionArray.Length); Assert.AreEqual(2, versionArray[0].Major); Task taskInt = JsonConvert.DeserializeObjectAsync("5"); taskInt.Wait(); Assert.AreEqual(5, taskInt.Result); var taskVersion = JsonConvert.DeserializeObjectAsync("'2.0'", new JsonSerializerSettings { Converters = {new VersionConverter()} }); taskVersion.Wait(); Assert.AreEqual(2, taskVersion.Result.Major); Movie p = new Movie(); p.Name = "Existing,"; Task taskVoid = JsonConvert.PopulateObjectAsync("{'Name':'Appended'}", p, new JsonSerializerSettings { Converters = new List { new JsonSerializerTest.StringAppenderConverter() } }); taskVoid.Wait(); Assert.AreEqual("Existing,Appended", p.Name); } #endif } }