X-Git-Url: https://code.grnet.gr/git/pithos-ms-client/blobdiff_plain/2b753c231bb911d42040013e144c17e264e75475..d78cbf094dc59fc605a766b8b2c1f45af67b135e:/trunk/Libraries/Json40r2/Source/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs?ds=sidebyside diff --git a/trunk/Libraries/Json40r2/Source/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/trunk/Libraries/Json40r2/Source/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs new file mode 100644 index 0000000..25d05eb --- /dev/null +++ b/trunk/Libraries/Json40r2/Source/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -0,0 +1,4314 @@ +#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; +#if !SILVERLIGHT && !PocketPC && !NET20 +using System.ComponentModel.DataAnnotations; +using System.Configuration; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Web.Script.Serialization; +#endif +using System.Text; +using NUnit.Framework; +using Newtonsoft.Json; +using System.IO; +using System.Collections; +using System.Xml; +using System.Xml.Serialization; +using System.Collections.ObjectModel; +using Newtonsoft.Json.Linq; +using System.Linq; +using Newtonsoft.Json.Converters; +#if !PocketPC && !NET20 && !WINDOWS_PHONE +using System.Runtime.Serialization.Json; +#endif +using Newtonsoft.Json.Tests.TestObjects; +using System.Runtime.Serialization; +using System.Globalization; +using Newtonsoft.Json.Utilities; +using System.Reflection; +#if !NET20 && !SILVERLIGHT +using System.Xml.Linq; +using System.Text.RegularExpressions; +using System.Collections.Specialized; +using System.Linq.Expressions; +#endif +#if !(NET35 || NET20 || WINDOWS_PHONE) +using System.Dynamic; +using System.ComponentModel; +#endif + +namespace Newtonsoft.Json.Tests.Serialization +{ + public class JsonSerializerTest : TestFixtureBase + { + [Test] + public void PersonTypedObjectDeserialization() + { + Store store = new Store(); + + string jsonText = JsonConvert.SerializeObject(store); + + Store deserializedStore = (Store)JsonConvert.DeserializeObject(jsonText, typeof(Store)); + + Assert.AreEqual(store.Establised, deserializedStore.Establised); + Assert.AreEqual(store.product.Count, deserializedStore.product.Count); + + Console.WriteLine(jsonText); + } + + [Test] + public void TypedObjectDeserialization() + { + Product product = new Product(); + + product.Name = "Apple"; + product.ExpiryDate = new DateTime(2008, 12, 28); + product.Price = 3.99M; + product.Sizes = new string[] { "Small", "Medium", "Large" }; + + string output = JsonConvert.SerializeObject(product); + //{ + // "Name": "Apple", + // "ExpiryDate": "\/Date(1230375600000+1300)\/", + // "Price": 3.99, + // "Sizes": [ + // "Small", + // "Medium", + // "Large" + // ] + //} + + Product deserializedProduct = (Product)JsonConvert.DeserializeObject(output, typeof(Product)); + + Assert.AreEqual("Apple", deserializedProduct.Name); + Assert.AreEqual(new DateTime(2008, 12, 28), deserializedProduct.ExpiryDate); + Assert.AreEqual(3.99, deserializedProduct.Price); + Assert.AreEqual("Small", deserializedProduct.Sizes[0]); + Assert.AreEqual("Medium", deserializedProduct.Sizes[1]); + Assert.AreEqual("Large", deserializedProduct.Sizes[2]); + } + + //[Test] + //public void Advanced() + //{ + // Product product = new Product(); + // product.ExpiryDate = new DateTime(2008, 12, 28); + + // JsonSerializer serializer = new JsonSerializer(); + // serializer.Converters.Add(new JavaScriptDateTimeConverter()); + // serializer.NullValueHandling = NullValueHandling.Ignore; + + // using (StreamWriter sw = new StreamWriter(@"c:\json.txt")) + // using (JsonWriter writer = new JsonTextWriter(sw)) + // { + // serializer.Serialize(writer, product); + // // {"ExpiryDate":new Date(1230375600000),"Price":0} + // } + //} + + [Test] + public void JsonConvertSerializer() + { + string value = @"{""Name"":""Orange"", ""Price"":3.99, ""ExpiryDate"":""01/24/2010 12:00:00""}"; + + Product p = JsonConvert.DeserializeObject(value, typeof(Product)) as Product; + + Assert.AreEqual("Orange", p.Name); + Assert.AreEqual(new DateTime(2010, 1, 24, 12, 0, 0), p.ExpiryDate); + Assert.AreEqual(3.99, p.Price); + } + + [Test] + public void DeserializeJavaScriptDate() + { + DateTime dateValue = new DateTime(2010, 3, 30); + Dictionary testDictionary = new Dictionary(); + testDictionary["date"] = dateValue; + + string jsonText = JsonConvert.SerializeObject(testDictionary); + +#if !PocketPC && !NET20 && !WINDOWS_PHONE + MemoryStream ms = new MemoryStream(); + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Dictionary)); + serializer.WriteObject(ms, testDictionary); + + byte[] data = ms.ToArray(); + string output = Encoding.UTF8.GetString(data, 0, data.Length); +#endif + + Dictionary deserializedDictionary = (Dictionary)JsonConvert.DeserializeObject(jsonText, typeof(Dictionary)); + DateTime deserializedDate = (DateTime)deserializedDictionary["date"]; + + Assert.AreEqual(dateValue, deserializedDate); + + Console.WriteLine("DeserializeJavaScriptDate"); + Console.WriteLine(jsonText); + Console.WriteLine(); + Console.WriteLine(jsonText); + } + + [Test] + public void TestMethodExecutorObject() + { + MethodExecutorObject executorObject = new MethodExecutorObject(); + executorObject.serverClassName = "BanSubs"; + executorObject.serverMethodParams = new object[] { "21321546", "101", "1236", "D:\\1.txt" }; + executorObject.clientGetResultFunction = "ClientBanSubsCB"; + + string output = JsonConvert.SerializeObject(executorObject); + + MethodExecutorObject executorObject2 = JsonConvert.DeserializeObject(output, typeof(MethodExecutorObject)) as MethodExecutorObject; + + Assert.AreNotSame(executorObject, executorObject2); + Assert.AreEqual(executorObject2.serverClassName, "BanSubs"); + Assert.AreEqual(executorObject2.serverMethodParams.Length, 4); + Assert.Contains("101", executorObject2.serverMethodParams); + Assert.AreEqual(executorObject2.clientGetResultFunction, "ClientBanSubsCB"); + } + +#if !SILVERLIGHT + [Test] + public void HashtableDeserialization() + { + string value = @"{""Name"":""Orange"", ""Price"":3.99, ""ExpiryDate"":""01/24/2010 12:00:00""}"; + + Hashtable p = JsonConvert.DeserializeObject(value, typeof(Hashtable)) as Hashtable; + + Assert.AreEqual("Orange", p["Name"].ToString()); + } + + [Test] + public void TypedHashtableDeserialization() + { + string value = @"{""Name"":""Orange"", ""Hash"":{""ExpiryDate"":""01/24/2010 12:00:00"",""UntypedArray"":[""01/24/2010 12:00:00""]}}"; + + TypedSubHashtable p = JsonConvert.DeserializeObject(value, typeof(TypedSubHashtable)) as TypedSubHashtable; + + Assert.AreEqual("01/24/2010 12:00:00", p.Hash["ExpiryDate"].ToString()); + Assert.AreEqual(@"[ + ""01/24/2010 12:00:00"" +]", p.Hash["UntypedArray"].ToString()); + } +#endif + + [Test] + public void SerializeDeserializeGetOnlyProperty() + { + string value = JsonConvert.SerializeObject(new GetOnlyPropertyClass()); + + GetOnlyPropertyClass c = JsonConvert.DeserializeObject(value); + + Assert.AreEqual(c.Field, "Field"); + Assert.AreEqual(c.GetOnlyProperty, "GetOnlyProperty"); + } + + [Test] + public void SerializeDeserializeSetOnlyProperty() + { + string value = JsonConvert.SerializeObject(new SetOnlyPropertyClass()); + + SetOnlyPropertyClass c = JsonConvert.DeserializeObject(value); + + Assert.AreEqual(c.Field, "Field"); + } + + [Test] + public void JsonIgnoreAttributeTest() + { + string json = JsonConvert.SerializeObject(new JsonIgnoreAttributeTestClass()); + + Assert.AreEqual(@"{""Field"":0,""Property"":21}", json); + + JsonIgnoreAttributeTestClass c = JsonConvert.DeserializeObject(@"{""Field"":99,""Property"":-1,""IgnoredField"":-1,""IgnoredObject"":[1,2,3,4,5]}"); + + Assert.AreEqual(0, c.IgnoredField); + Assert.AreEqual(99, c.Field); + } + + [Test] + public void GoogleSearchAPI() + { + string json = @"{ + results: + [ + { + GsearchResultClass:""GwebSearch"", + unescapedUrl : ""http://www.google.com/"", + url : ""http://www.google.com/"", + visibleUrl : ""www.google.com"", + cacheUrl : +""http://www.google.com/search?q=cache:zhool8dxBV4J:www.google.com"", + title : ""Google"", + titleNoFormatting : ""Google"", + content : ""Enables users to search the Web, Usenet, and +images. Features include PageRank, caching and translation of +results, and an option to find similar pages."" + }, + { + GsearchResultClass:""GwebSearch"", + unescapedUrl : ""http://news.google.com/"", + url : ""http://news.google.com/"", + visibleUrl : ""news.google.com"", + cacheUrl : +""http://www.google.com/search?q=cache:Va_XShOz_twJ:news.google.com"", + title : ""Google News"", + titleNoFormatting : ""Google News"", + content : ""Aggregated headlines and a search engine of many of the world's news sources."" + }, + + { + GsearchResultClass:""GwebSearch"", + unescapedUrl : ""http://groups.google.com/"", + url : ""http://groups.google.com/"", + visibleUrl : ""groups.google.com"", + cacheUrl : +""http://www.google.com/search?q=cache:x2uPD3hfkn0J:groups.google.com"", + title : ""Google Groups"", + titleNoFormatting : ""Google Groups"", + content : ""Enables users to search and browse the Usenet +archives which consist of over 700 million messages, and post new +comments."" + }, + + { + GsearchResultClass:""GwebSearch"", + unescapedUrl : ""http://maps.google.com/"", + url : ""http://maps.google.com/"", + visibleUrl : ""maps.google.com"", + cacheUrl : +""http://www.google.com/search?q=cache:dkf5u2twBXIJ:maps.google.com"", + title : ""Google Maps"", + titleNoFormatting : ""Google Maps"", + content : ""Provides directions, interactive maps, and +satellite/aerial imagery of the United States. Can also search by +keyword such as type of business."" + } + ], + + adResults: + [ + { + GsearchResultClass:""GwebSearch.ad"", + title : ""Gartner Symposium/ITxpo"", + content1 : ""Meet brilliant Gartner IT analysts"", + content2 : ""20-23 May 2007- Barcelona, Spain"", + url : +""http://www.google.com/url?sa=L&ai=BVualExYGRo3hD5ianAPJvejjD8-s6ye7kdTwArbI4gTAlrECEAEYASDXtMMFOAFQubWAjvr_____AWDXw_4EiAEBmAEAyAEBgAIB&num=1&q=http://www.gartner.com/it/sym/2007/spr8/spr8.jsp%3Fsrc%3D_spain_07_%26WT.srch%3D1&usg=__CxRH06E4Xvm9Muq13S4MgMtnziY="", + + impressionUrl : +""http://www.google.com/uds/css/ad-indicator-on.gif?ai=BVualExYGRo3hD5ianAPJvejjD8-s6ye7kdTwArbI4gTAlrECEAEYASDXtMMFOAFQubWAjvr_____AWDXw_4EiAEBmAEAyAEBgAIB"", + + unescapedUrl : +""http://www.google.com/url?sa=L&ai=BVualExYGRo3hD5ianAPJvejjD8-s6ye7kdTwArbI4gTAlrECEAEYASDXtMMFOAFQubWAjvr_____AWDXw_4EiAEBmAEAyAEBgAIB&num=1&q=http://www.gartner.com/it/sym/2007/spr8/spr8.jsp%3Fsrc%3D_spain_07_%26WT.srch%3D1&usg=__CxRH06E4Xvm9Muq13S4MgMtnziY="", + + visibleUrl : ""www.gartner.com"" + } + ] +} +"; + object o = JsonConvert.DeserializeObject(json); + string s = string.Empty; + s += s; + } + + [Test] + public void TorrentDeserializeTest() + { + string jsonText = @"{ +"""":"""", +""label"": [ + [""SomeName"",6] +], +""torrents"": [ + [""192D99A5C943555CB7F00A852821CF6D6DB3008A"",201,""filename.avi"",178311826,1000,178311826,72815250,408,1603,7,121430,""NameOfLabelPrevioslyDefined"",3,6,0,8,128954,-1,0], +], +""torrentc"": ""1816000723"" +}"; + + JObject o = (JObject)JsonConvert.DeserializeObject(jsonText); + Assert.AreEqual(4, o.Children().Count()); + + JToken torrentsArray = (JToken)o["torrents"]; + JToken nestedTorrentsArray = (JToken)torrentsArray[0]; + Assert.AreEqual(nestedTorrentsArray.Children().Count(), 19); + } + + [Test] + public void JsonPropertyClassSerialize() + { + JsonPropertyClass test = new JsonPropertyClass(); + test.Pie = "Delicious"; + test.SweetCakesCount = int.MaxValue; + + string jsonText = JsonConvert.SerializeObject(test); + + Assert.AreEqual(@"{""pie"":""Delicious"",""pie1"":""PieChart!"",""sweet_cakes_count"":2147483647}", jsonText); + + JsonPropertyClass test2 = JsonConvert.DeserializeObject(jsonText); + + Assert.AreEqual(test.Pie, test2.Pie); + Assert.AreEqual(test.SweetCakesCount, test2.SweetCakesCount); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"A member with the name 'pie' already exists on 'Newtonsoft.Json.Tests.TestObjects.BadJsonPropertyClass'. Use the JsonPropertyAttribute to specify another name.")] + public void BadJsonPropertyClassSerialize() + { + JsonConvert.SerializeObject(new BadJsonPropertyClass()); + } + + [Test] + public void InheritedListSerialize() + { + Article a1 = new Article("a1"); + Article a2 = new Article("a2"); + + ArticleCollection articles1 = new ArticleCollection(); + articles1.Add(a1); + articles1.Add(a2); + + string jsonText = JsonConvert.SerializeObject(articles1); + + ArticleCollection articles2 = JsonConvert.DeserializeObject(jsonText); + + Assert.AreEqual(articles1.Count, articles2.Count); + Assert.AreEqual(articles1[0].Name, articles2[0].Name); + } + + [Test] + public void ReadOnlyCollectionSerialize() + { + ReadOnlyCollection r1 = new ReadOnlyCollection(new int[] { 0, 1, 2, 3, 4 }); + + string jsonText = JsonConvert.SerializeObject(r1); + + ReadOnlyCollection r2 = JsonConvert.DeserializeObject>(jsonText); + + CollectionAssert.AreEqual(r1, r2); + } + +#if !PocketPC && !NET20 && !WINDOWS_PHONE + [Test] + public void Unicode() + { + string json = @"[""PRE\u003cPOST""]"; + + DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List)); + List dataContractResult = (List)s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json))); + + List jsonNetResult = JsonConvert.DeserializeObject>(json); + + Assert.AreEqual(1, jsonNetResult.Count); + Assert.AreEqual(dataContractResult[0], jsonNetResult[0]); + } + + [Test] + public void BackslashEqivilence() + { + string json = @"[""vvv\/vvv\tvvv\""vvv\bvvv\nvvv\rvvv\\vvv\fvvv""]"; + +#if !SILVERLIGHT + JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer(); + List javaScriptSerializerResult = javaScriptSerializer.Deserialize>(json); +#endif + + DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List)); + List dataContractResult = (List)s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json))); + + List jsonNetResult = JsonConvert.DeserializeObject>(json); + + Assert.AreEqual(1, jsonNetResult.Count); + Assert.AreEqual(dataContractResult[0], jsonNetResult[0]); +#if !SILVERLIGHT + Assert.AreEqual(javaScriptSerializerResult[0], jsonNetResult[0]); +#endif + } + + [Test] + [ExpectedException(typeof(JsonReaderException), ExpectedMessage = @"Bad JSON escape sequence: \j. Line 1, position 7.")] + public void InvalidBackslash() + { + string json = @"[""vvv\jvvv""]"; + + JsonConvert.DeserializeObject>(json); + } + + [Test] + public void DateTimeTest() + { + List testDates = new List { + 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)); + s.WriteObject(ms, testDates); + ms.Seek(0, SeekOrigin.Begin); + StreamReader sr = new StreamReader(ms); + + string expected = sr.ReadToEnd(); + + result = JsonConvert.SerializeObject(testDates); + Assert.AreEqual(expected, result); + } + + [Test] + public void DateTimeOffset() + { + List testDates = new List { + 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 = JsonConvert.SerializeObject(testDates); + Assert.AreEqual(@"[""\/Date(-59011455539000+0000)\/"",""\/Date(946688461000+0000)\/"",""\/Date(946641661000+1300)\/"",""\/Date(946701061000-0330)\/""]", result); + } +#endif + + [Test] + public void NonStringKeyDictionary() + { + Dictionary values = new Dictionary(); + values.Add(-5, 6); + values.Add(int.MinValue, int.MaxValue); + + string json = JsonConvert.SerializeObject(values); + + Assert.AreEqual(@"{""-5"":6,""-2147483648"":2147483647}", json); + + Dictionary newValues = JsonConvert.DeserializeObject>(json); + + CollectionAssert.AreEqual(values, newValues); + } + + [Test] + public void AnonymousObjectSerialization() + { + 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 = JsonConvert.SerializeObject(anonymous); + Assert.AreEqual(@"{""StringValue"":""I am a string"",""IntValue"":2147483647,""NestedAnonymous"":{""NestedValue"":255},""NestedArray"":[1,2],""Product"":{""Name"":""TestProduct"",""ExpiryDate"":""\/Date(946684800000)\/"",""Price"":0.0,""Sizes"":null}}", json); + + anonymous = JsonConvert.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] + public void CustomCollectionSerialization() + { + ProductCollection collection = new ProductCollection() + { + new Product() { Name = "Test1" }, + new Product() { Name = "Test2" }, + new Product() { Name = "Test3" } + }; + + JsonSerializer jsonSerializer = new JsonSerializer(); + jsonSerializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + + StringWriter sw = new StringWriter(); + + jsonSerializer.Serialize(sw, collection); + + Assert.AreEqual(@"[{""Name"":""Test1"",""ExpiryDate"":""\/Date(946684800000)\/"",""Price"":0.0,""Sizes"":null},{""Name"":""Test2"",""ExpiryDate"":""\/Date(946684800000)\/"",""Price"":0.0,""Sizes"":null},{""Name"":""Test3"",""ExpiryDate"":""\/Date(946684800000)\/"",""Price"":0.0,""Sizes"":null}]", + sw.GetStringBuilder().ToString()); + + ProductCollection collectionNew = (ProductCollection)jsonSerializer.Deserialize(new JsonTextReader(new StringReader(sw.GetStringBuilder().ToString())), typeof(ProductCollection)); + + CollectionAssert.AreEqual(collection, collectionNew); + } + + [Test] + public void SerializeObject() + { + string json = JsonConvert.SerializeObject(new object()); + Assert.AreEqual("{}", json); + } + + [Test] + public void SerializeNull() + { + string json = JsonConvert.SerializeObject(null); + Assert.AreEqual("null", json); + } + + [Test] + public void CanDeserializeIntArrayWhenNotFirstPropertyInJson() + { + string json = "{foo:'hello',bar:[1,2,3]}"; + ClassWithArray wibble = JsonConvert.DeserializeObject(json); + Assert.AreEqual("hello", wibble.Foo); + + Assert.AreEqual(4, wibble.Bar.Count); + Assert.AreEqual(int.MaxValue, wibble.Bar[0]); + Assert.AreEqual(1, wibble.Bar[1]); + Assert.AreEqual(2, wibble.Bar[2]); + Assert.AreEqual(3, wibble.Bar[3]); + } + + [Test] + public void CanDeserializeIntArray_WhenArrayIsFirstPropertyInJson() + { + string json = "{bar:[1,2,3], foo:'hello'}"; + ClassWithArray wibble = JsonConvert.DeserializeObject(json); + Assert.AreEqual("hello", wibble.Foo); + + Assert.AreEqual(4, wibble.Bar.Count); + Assert.AreEqual(int.MaxValue, wibble.Bar[0]); + Assert.AreEqual(1, wibble.Bar[1]); + Assert.AreEqual(2, wibble.Bar[2]); + Assert.AreEqual(3, wibble.Bar[3]); + } + + [Test] + public void ObjectCreationHandlingReplace() + { + string json = "{bar:[1,2,3], foo:'hello'}"; + + JsonSerializer s = new JsonSerializer(); + s.ObjectCreationHandling = ObjectCreationHandling.Replace; + + ClassWithArray wibble = (ClassWithArray)s.Deserialize(new StringReader(json), typeof(ClassWithArray)); + + Assert.AreEqual("hello", wibble.Foo); + + Assert.AreEqual(1, wibble.Bar.Count); + } + + [Test] + public void CanDeserializeSerializedJson() + { + ClassWithArray wibble = new ClassWithArray(); + wibble.Foo = "hello"; + wibble.Bar.Add(1); + wibble.Bar.Add(2); + wibble.Bar.Add(3); + string json = JsonConvert.SerializeObject(wibble); + + ClassWithArray wibbleOut = JsonConvert.DeserializeObject(json); + Assert.AreEqual("hello", wibbleOut.Foo); + + Assert.AreEqual(5, wibbleOut.Bar.Count); + Assert.AreEqual(int.MaxValue, wibbleOut.Bar[0]); + Assert.AreEqual(int.MaxValue, wibbleOut.Bar[1]); + Assert.AreEqual(1, wibbleOut.Bar[2]); + Assert.AreEqual(2, wibbleOut.Bar[3]); + Assert.AreEqual(3, wibbleOut.Bar[4]); + } + + [Test] + public void SerializeConverableObjects() + { + string json = JsonConvert.SerializeObject(new ConverableMembers()); + + Assert.AreEqual(@"{""String"":""string"",""Int32"":2147483647,""UInt32"":4294967295,""Byte"":255,""SByte"":127,""Short"":32767,""UShort"":65535,""Long"":9223372036854775807,""ULong"":9223372036854775807,""Double"":1.7976931348623157E+308,""Float"":3.40282347E+38,""DBNull"":null,""Bool"":true,""Char"":""\u0000""}", json); + + ConverableMembers c = JsonConvert.DeserializeObject(json); + Assert.AreEqual("string", c.String); + Assert.AreEqual(double.MaxValue, c.Double); + Assert.AreEqual(DBNull.Value, c.DBNull); + } + + [Test] + public void SerializeStack() + { + Stack s = new Stack(); + s.Push(1); + s.Push(2); + s.Push(3); + + string json = JsonConvert.SerializeObject(s); + Assert.AreEqual("[3,2,1]", json); + } + + [Test] + public void GuidTest() + { + Guid guid = new Guid("BED7F4EA-1A96-11d2-8F08-00A0C9A6186D"); + + string json = JsonConvert.SerializeObject(new ClassWithGuid { GuidField = guid }); + Assert.AreEqual(@"{""GuidField"":""bed7f4ea-1a96-11d2-8f08-00a0c9a6186d""}", json); + + ClassWithGuid c = JsonConvert.DeserializeObject(json); + Assert.AreEqual(guid, c.GuidField); + } + + [Test] + public void EnumTest() + { + string json = JsonConvert.SerializeObject(StringComparison.CurrentCultureIgnoreCase); + Assert.AreEqual(@"1", json); + + StringComparison s = JsonConvert.DeserializeObject(json); + Assert.AreEqual(StringComparison.CurrentCultureIgnoreCase, s); + } + + public class ClassWithTimeSpan + { + public TimeSpan TimeSpanField; + } + + [Test] + public void TimeSpanTest() + { + TimeSpan ts = new TimeSpan(00, 23, 59, 1); + + string json = JsonConvert.SerializeObject(new ClassWithTimeSpan { TimeSpanField = ts }, Formatting.Indented); + Assert.AreEqual(@"{ + ""TimeSpanField"": ""23:59:01"" +}", json); + + ClassWithTimeSpan c = JsonConvert.DeserializeObject(json); + Assert.AreEqual(ts, c.TimeSpanField); + } + + [Test] + public void JsonIgnoreAttributeOnClassTest() + { + string json = JsonConvert.SerializeObject(new JsonIgnoreAttributeOnClassTestClass()); + + Assert.AreEqual(@"{""TheField"":0,""Property"":21}", json); + + JsonIgnoreAttributeOnClassTestClass c = JsonConvert.DeserializeObject(@"{""TheField"":99,""Property"":-1,""IgnoredField"":-1}"); + + Assert.AreEqual(0, c.IgnoredField); + Assert.AreEqual(99, c.Field); + } + +#if !SILVERLIGHT + [Test] + public void SerializeArrayAsArrayList() + { + string jsonText = @"[3, ""somestring"",[1,2,3],{}]"; + ArrayList o = JsonConvert.DeserializeObject(jsonText); + + Assert.AreEqual(4, o.Count); + Assert.AreEqual(3, ((JArray)o[2]).Count); + Assert.AreEqual(0, ((JObject)o[3]).Count); + } +#endif + + [Test] + public void SerializeMemberGenericList() + { + Name name = new Name("The Idiot in Next To Me"); + + PhoneNumber p1 = new PhoneNumber("555-1212"); + PhoneNumber p2 = new PhoneNumber("444-1212"); + + name.pNumbers.Add(p1); + name.pNumbers.Add(p2); + + string json = JsonConvert.SerializeObject(name, Formatting.Indented); + + Assert.AreEqual(@"{ + ""personsName"": ""The Idiot in Next To Me"", + ""pNumbers"": [ + { + ""phoneNumber"": ""555-1212"" + }, + { + ""phoneNumber"": ""444-1212"" + } + ] +}", json); + + Name newName = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("The Idiot in Next To Me", newName.personsName); + + // not passed in as part of the constructor but assigned to pNumbers property + Assert.AreEqual(2, newName.pNumbers.Count); + Assert.AreEqual("555-1212", newName.pNumbers[0].phoneNumber); + Assert.AreEqual("444-1212", newName.pNumbers[1].phoneNumber); + } + + [Test] + public void ConstructorCaseSensitivity() + { + ConstructorCaseSensitivityClass c = new ConstructorCaseSensitivityClass("param1", "Param1", "Param2"); + + string json = JsonConvert.SerializeObject(c); + + ConstructorCaseSensitivityClass deserialized = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("param1", deserialized.param1); + Assert.AreEqual("Param1", deserialized.Param1); + Assert.AreEqual("Param2", deserialized.Param2); + } + + [Test] + public void SerializerShouldUseClassConverter() + { + ConverterPrecedenceClass c1 = new ConverterPrecedenceClass("!Test!"); + + string json = JsonConvert.SerializeObject(c1); + Assert.AreEqual(@"[""Class"",""!Test!""]", json); + + ConverterPrecedenceClass c2 = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("!Test!", c2.TestValue); + } + + [Test] + public void SerializerShouldUseClassConverterOverArgumentConverter() + { + ConverterPrecedenceClass c1 = new ConverterPrecedenceClass("!Test!"); + + string json = JsonConvert.SerializeObject(c1, new ArgumentConverterPrecedenceClassConverter()); + Assert.AreEqual(@"[""Class"",""!Test!""]", json); + + ConverterPrecedenceClass c2 = JsonConvert.DeserializeObject(json, new ArgumentConverterPrecedenceClassConverter()); + + Assert.AreEqual("!Test!", c2.TestValue); + } + + [Test] + public void SerializerShouldUseMemberConverter() + { + DateTime testDate = new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc); + MemberConverterClass m1 = new MemberConverterClass { DefaultConverter = testDate, MemberConverter = testDate }; + + string json = JsonConvert.SerializeObject(m1); + Assert.AreEqual(@"{""DefaultConverter"":""\/Date(0)\/"",""MemberConverter"":""1970-01-01T00:00:00Z""}", json); + + MemberConverterClass m2 = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(testDate, m2.DefaultConverter); + Assert.AreEqual(testDate, m2.MemberConverter); + } + + [Test] + public void SerializerShouldUseMemberConverterOverArgumentConverter() + { + DateTime testDate = new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc); + MemberConverterClass m1 = new MemberConverterClass { DefaultConverter = testDate, MemberConverter = testDate }; + + string json = JsonConvert.SerializeObject(m1, new JavaScriptDateTimeConverter()); + Assert.AreEqual(@"{""DefaultConverter"":new Date(0),""MemberConverter"":""1970-01-01T00:00:00Z""}", json); + + MemberConverterClass m2 = JsonConvert.DeserializeObject(json, new JavaScriptDateTimeConverter()); + + Assert.AreEqual(testDate, m2.DefaultConverter); + Assert.AreEqual(testDate, m2.MemberConverter); + } + + [Test] + public void ConverterAttributeExample() + { + DateTime date = Convert.ToDateTime("1970-01-01T00:00:00Z").ToUniversalTime(); + + MemberConverterClass c = new MemberConverterClass + { + DefaultConverter = date, + MemberConverter = date + }; + + string json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Console.WriteLine(json); + //{ + // "DefaultConverter": "\/Date(0)\/", + // "MemberConverter": "1970-01-01T00:00:00Z" + //} + } + + [Test] + public void SerializerShouldUseMemberConverterOverClassAndArgumentConverter() + { + ClassAndMemberConverterClass c1 = new ClassAndMemberConverterClass(); + c1.DefaultConverter = new ConverterPrecedenceClass("DefaultConverterValue"); + c1.MemberConverter = new ConverterPrecedenceClass("MemberConverterValue"); + + string json = JsonConvert.SerializeObject(c1, new ArgumentConverterPrecedenceClassConverter()); + Assert.AreEqual(@"{""DefaultConverter"":[""Class"",""DefaultConverterValue""],""MemberConverter"":[""Member"",""MemberConverterValue""]}", json); + + ClassAndMemberConverterClass c2 = JsonConvert.DeserializeObject(json, new ArgumentConverterPrecedenceClassConverter()); + + Assert.AreEqual("DefaultConverterValue", c2.DefaultConverter.TestValue); + Assert.AreEqual("MemberConverterValue", c2.MemberConverter.TestValue); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "JsonConverter IsoDateTimeConverter on Newtonsoft.Json.Tests.TestObjects.IncompatibleJsonAttributeClass is not compatible with member type IncompatibleJsonAttributeClass.")] + public void IncompatibleJsonAttributeShouldThrow() + { + IncompatibleJsonAttributeClass c = new IncompatibleJsonAttributeClass(); + JsonConvert.SerializeObject(c); + } + + [Test] + public void GenericAbstractProperty() + { + string json = JsonConvert.SerializeObject(new GenericImpl()); + Assert.AreEqual(@"{""Id"":0}", json); + } + + [Test] + public void DeserializeNullable() + { + string json; + + json = JsonConvert.SerializeObject((int?)null); + Assert.AreEqual("null", json); + + json = JsonConvert.SerializeObject((int?)1); + Assert.AreEqual("1", json); + } + + [Test] + public void SerializeJsonRaw() + { + PersonRaw personRaw = new PersonRaw + { + FirstName = "FirstNameValue", + RawContent = new JRaw("[1,2,3,4,5]"), + LastName = "LastNameValue" + }; + + string json; + + json = JsonConvert.SerializeObject(personRaw); + Assert.AreEqual(@"{""first_name"":""FirstNameValue"",""RawContent"":[1,2,3,4,5],""last_name"":""LastNameValue""}", json); + } + + [Test] + public void DeserializeJsonRaw() + { + string json = @"{""first_name"":""FirstNameValue"",""RawContent"":[1,2,3,4,5],""last_name"":""LastNameValue""}"; + + PersonRaw personRaw = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("FirstNameValue", personRaw.FirstName); + Assert.AreEqual("[1,2,3,4,5]", personRaw.RawContent.ToString()); + Assert.AreEqual("LastNameValue", personRaw.LastName); + } + + + [Test] + public void DeserializeNullableMember() + { + UserNullable userNullablle = new UserNullable + { + Id = new Guid("AD6205E8-0DF4-465d-AEA6-8BA18E93A7E7"), + FName = "FirstValue", + LName = "LastValue", + RoleId = 5, + NullableRoleId = 6, + NullRoleId = null, + Active = true + }; + + string json = JsonConvert.SerializeObject(userNullablle); + + Assert.AreEqual(@"{""Id"":""ad6205e8-0df4-465d-aea6-8ba18e93a7e7"",""FName"":""FirstValue"",""LName"":""LastValue"",""RoleId"":5,""NullableRoleId"":6,""NullRoleId"":null,""Active"":true}", json); + + UserNullable userNullablleDeserialized = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(new Guid("AD6205E8-0DF4-465d-AEA6-8BA18E93A7E7"), userNullablleDeserialized.Id); + Assert.AreEqual("FirstValue", userNullablleDeserialized.FName); + Assert.AreEqual("LastValue", userNullablleDeserialized.LName); + Assert.AreEqual(5, userNullablleDeserialized.RoleId); + Assert.AreEqual(6, userNullablleDeserialized.NullableRoleId); + Assert.AreEqual(null, userNullablleDeserialized.NullRoleId); + Assert.AreEqual(true, userNullablleDeserialized.Active); + } + + [Test] + public void DeserializeInt64ToNullableDouble() + { + string json = @"{""Height"":1}"; + + DoubleClass c = JsonConvert.DeserializeObject(json); + Assert.AreEqual(1, c.Height); + } + + [Test] + public void SerializeTypeProperty() + { + string boolRef = typeof(bool).AssemblyQualifiedName; + TypeClass typeClass = new TypeClass { TypeProperty = typeof(bool) }; + + string json = JsonConvert.SerializeObject(typeClass); + Assert.AreEqual(@"{""TypeProperty"":""" + boolRef + @"""}", json); + + TypeClass typeClass2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual(typeof(bool), typeClass2.TypeProperty); + + string jsonSerializerTestRef = typeof(JsonSerializerTest).AssemblyQualifiedName; + typeClass = new TypeClass { TypeProperty = typeof(JsonSerializerTest) }; + + json = JsonConvert.SerializeObject(typeClass); + Assert.AreEqual(@"{""TypeProperty"":""" + jsonSerializerTestRef + @"""}", json); + + typeClass2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual(typeof(JsonSerializerTest), typeClass2.TypeProperty); + } + + [Test] + public void RequiredMembersClass() + { + RequiredMembersClass c = new RequiredMembersClass() + { + BirthDate = new DateTime(2000, 12, 20, 10, 55, 55, DateTimeKind.Utc), + FirstName = "Bob", + LastName = "Smith", + MiddleName = "Cosmo" + }; + + string json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Assert.AreEqual(@"{ + ""FirstName"": ""Bob"", + ""MiddleName"": ""Cosmo"", + ""LastName"": ""Smith"", + ""BirthDate"": ""\/Date(977309755000)\/"" +}", json); + + RequiredMembersClass c2 = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("Bob", c2.FirstName); + Assert.AreEqual(new DateTime(2000, 12, 20, 10, 55, 55, DateTimeKind.Utc), c2.BirthDate); + } + + [Test] + public void DeserializeRequiredMembersClassWithNullValues() + { + string json = @"{ + ""FirstName"": ""I can't be null bro!"", + ""MiddleName"": null, + ""LastName"": null, + ""BirthDate"": ""\/Date(977309755000)\/"" +}"; + + RequiredMembersClass c = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("I can't be null bro!", c.FirstName); + Assert.AreEqual(null, c.MiddleName); + Assert.AreEqual(null, c.LastName); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Required property 'FirstName' expects a value but got null.")] + public void DeserializeRequiredMembersClassNullRequiredValueProperty() + { + string json = @"{ + ""FirstName"": null, + ""MiddleName"": null, + ""LastName"": null, + ""BirthDate"": ""\/Date(977309755000)\/"" +}"; + + JsonConvert.DeserializeObject(json); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Cannot write a null value for property 'FirstName'. Property requires a value.")] + public void SerializeRequiredMembersClassNullRequiredValueProperty() + { + RequiredMembersClass requiredMembersClass = new RequiredMembersClass + { + FirstName = null, + BirthDate = new DateTime(2000, 10, 10, 10, 10, 10, DateTimeKind.Utc), + LastName = null, + MiddleName = null + }; + + string json = JsonConvert.SerializeObject(requiredMembersClass); + Console.WriteLine(json); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Required property 'LastName' not found in JSON.")] + public void RequiredMembersClassMissingRequiredProperty() + { + string json = @"{ + ""FirstName"": ""Bob"" +}"; + + JsonConvert.DeserializeObject(json); + } + + [Test] + public void SerializeJaggedArray() + { + JaggedArray aa = new JaggedArray(); + aa.Before = "Before!"; + aa.After = "After!"; + aa.Coordinates = new[] { new[] { 1, 1 }, new[] { 1, 2 }, new[] { 2, 1 }, new[] { 2, 2 } }; + + string json = JsonConvert.SerializeObject(aa); + + Assert.AreEqual(@"{""Before"":""Before!"",""Coordinates"":[[1,1],[1,2],[2,1],[2,2]],""After"":""After!""}", json); + } + + [Test] + public void DeserializeJaggedArray() + { + string json = @"{""Before"":""Before!"",""Coordinates"":[[1,1],[1,2],[2,1],[2,2]],""After"":""After!""}"; + + JaggedArray aa = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("Before!", aa.Before); + Assert.AreEqual("After!", aa.After); + Assert.AreEqual(4, aa.Coordinates.Length); + Assert.AreEqual(2, aa.Coordinates[0].Length); + Assert.AreEqual(1, aa.Coordinates[0][0]); + Assert.AreEqual(2, aa.Coordinates[1][1]); + + string after = JsonConvert.SerializeObject(aa); + + Assert.AreEqual(json, after); + } + + [Test] + public void DeserializeGoogleGeoCode() + { + string json = @"{ + ""name"": ""1600 Amphitheatre Parkway, Mountain View, CA, USA"", + ""Status"": { + ""code"": 200, + ""request"": ""geocode"" + }, + ""Placemark"": [ + { + ""address"": ""1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA"", + ""AddressDetails"": { + ""Country"": { + ""CountryNameCode"": ""US"", + ""AdministrativeArea"": { + ""AdministrativeAreaName"": ""CA"", + ""SubAdministrativeArea"": { + ""SubAdministrativeAreaName"": ""Santa Clara"", + ""Locality"": { + ""LocalityName"": ""Mountain View"", + ""Thoroughfare"": { + ""ThoroughfareName"": ""1600 Amphitheatre Pkwy"" + }, + ""PostalCode"": { + ""PostalCodeNumber"": ""94043"" + } + } + } + } + }, + ""Accuracy"": 8 + }, + ""Point"": { + ""coordinates"": [-122.083739, 37.423021, 0] + } + } + ] +}"; + + GoogleMapGeocoderStructure jsonGoogleMapGeocoder = JsonConvert.DeserializeObject(json); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Could not create an instance of type Newtonsoft.Json.Tests.TestObjects.ICo. Type is an interface or abstract class and cannot be instantated.")] + public void DeserializeInterfaceProperty() + { + InterfacePropertyTestClass testClass = new InterfacePropertyTestClass(); + testClass.co = new Co(); + String strFromTest = JsonConvert.SerializeObject(testClass); + InterfacePropertyTestClass testFromDe = (InterfacePropertyTestClass)JsonConvert.DeserializeObject(strFromTest, typeof(InterfacePropertyTestClass)); + } + + private Person GetPerson() + { + Person person = new Person + { + Name = "Mike Manager", + BirthDate = new DateTime(1983, 8, 3, 0, 0, 0, DateTimeKind.Utc), + Department = "IT", + LastModified = new DateTime(2009, 2, 15, 0, 0, 0, DateTimeKind.Utc) + }; + return person; + } + + //[Test] + public void WriteJsonToFile() + { + //Person person = GetPerson(); + + //string json = JsonConvert.SerializeObject(person, Formatting.Indented); + + //File.WriteAllText(@"c:\person.json", json); + + Person person = GetPerson(); + + using (FileStream fs = System.IO.File.Open(@"c:\person.json", FileMode.CreateNew)) + using (StreamWriter sw = new StreamWriter(fs)) + using (JsonWriter jw = new JsonTextWriter(sw)) + { + jw.Formatting = Formatting.Indented; + + JsonSerializer serializer = new JsonSerializer(); + serializer.Serialize(jw, person); + } + } + + [Test] + public void WriteJsonDates() + { + LogEntry entry = new LogEntry + { + LogDate = new DateTime(2009, 2, 15, 0, 0, 0, DateTimeKind.Utc), + Details = "Application started." + }; + + string defaultJson = JsonConvert.SerializeObject(entry); + // {"Details":"Application started.","LogDate":"\/Date(1234656000000)\/"} + + string isoJson = JsonConvert.SerializeObject(entry, new IsoDateTimeConverter()); + // {"Details":"Application started.","LogDate":"2009-02-15T00:00:00.0000000Z"} + + string javascriptJson = JsonConvert.SerializeObject(entry, new JavaScriptDateTimeConverter()); + // {"Details":"Application started.","LogDate":new Date(1234656000000)} + + Console.WriteLine(defaultJson); + Console.WriteLine(isoJson); + Console.WriteLine(javascriptJson); + } + + public void GenericListAndDictionaryInterfaceProperties() + { + GenericListAndDictionaryInterfaceProperties o = new GenericListAndDictionaryInterfaceProperties(); + o.IDictionaryProperty = new Dictionary + { + {"one", 1}, + {"two", 2}, + {"three", 3} + }; + o.IListProperty = new List + { + 1, 2, 3 + }; + o.IEnumerableProperty = new List + { + 4, 5, 6 + }; + + string json = JsonConvert.SerializeObject(o, Formatting.Indented); + + Assert.AreEqual(@"{ + ""IEnumerableProperty"": [ + 4, + 5, + 6 + ], + ""IListProperty"": [ + 1, + 2, + 3 + ], + ""IDictionaryProperty"": { + ""one"": 1, + ""two"": 2, + ""three"": 3 + } +}", json); + + GenericListAndDictionaryInterfaceProperties deserializedObject = JsonConvert.DeserializeObject(json); + Assert.IsNotNull(deserializedObject); + + CollectionAssert.AreEqual(o.IListProperty.ToArray(), deserializedObject.IListProperty.ToArray()); + CollectionAssert.AreEqual(o.IEnumerableProperty.ToArray(), deserializedObject.IEnumerableProperty.ToArray()); + CollectionAssert.AreEqual(o.IDictionaryProperty.ToArray(), deserializedObject.IDictionaryProperty.ToArray()); + } + + [Test] + public void DeserializeBestMatchPropertyCase() + { + string json = @"{ + ""firstName"": ""firstName"", + ""FirstName"": ""FirstName"", + ""LastName"": ""LastName"", + ""lastName"": ""lastName"", +}"; + + PropertyCase o = JsonConvert.DeserializeObject(json); + Assert.IsNotNull(o); + + Assert.AreEqual("firstName", o.firstName); + Assert.AreEqual("FirstName", o.FirstName); + Assert.AreEqual("LastName", o.LastName); + Assert.AreEqual("lastName", o.lastName); + } + + [Test] + public void DeserializePropertiesOnToNonDefaultConstructor() + { + SubKlass i = new SubKlass("my subprop"); + i.SuperProp = "overrided superprop"; + + string json = JsonConvert.SerializeObject(i); + Assert.AreEqual(@"{""SubProp"":""my subprop"",""SuperProp"":""overrided superprop""}", json); + + SubKlass ii = JsonConvert.DeserializeObject(json); + + string newJson = JsonConvert.SerializeObject(ii); + Assert.AreEqual(@"{""SubProp"":""my subprop"",""SuperProp"":""overrided superprop""}", newJson); + } + + [Test] + public void JsonPropertyWithHandlingValues() + { + JsonPropertyWithHandlingValues o = new JsonPropertyWithHandlingValues(); + o.DefaultValueHandlingIgnoreProperty = "Default!"; + o.DefaultValueHandlingIncludeProperty = "Default!"; + + string json = JsonConvert.SerializeObject(o, Formatting.Indented); + + Assert.AreEqual(@"{ + ""DefaultValueHandlingIncludeProperty"": ""Default!"", + ""NullValueHandlingIncludeProperty"": null, + ""ReferenceLoopHandlingErrorProperty"": null, + ""ReferenceLoopHandlingIgnoreProperty"": null, + ""ReferenceLoopHandlingSerializeProperty"": null +}", json); + + json = JsonConvert.SerializeObject(o, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); + + Assert.AreEqual(@"{ + ""DefaultValueHandlingIncludeProperty"": ""Default!"", + ""NullValueHandlingIncludeProperty"": null +}", json); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException))] + public void JsonPropertyWithHandlingValues_ReferenceLoopError() + { + JsonPropertyWithHandlingValues o = new JsonPropertyWithHandlingValues(); + o.ReferenceLoopHandlingErrorProperty = o; + + JsonConvert.SerializeObject(o, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); + } + + [Test] + public void PartialClassDeserialize() + { + string json = @"{ + ""request"": ""ux.settings.update"", + ""sid"": ""14c561bd-32a8-457e-b4e5-4bba0832897f"", + ""uid"": ""30c39065-0f31-de11-9442-001e3786a8ec"", + ""fidOrder"": [ + ""id"", + ""andytest_name"", + ""andytest_age"", + ""andytest_address"", + ""andytest_phone"", + ""date"", + ""title"", + ""titleId"" + ], + ""entityName"": ""Andy Test"", + ""setting"": ""entity.field.order"" +}"; + + RequestOnly r = JsonConvert.DeserializeObject(json); + Assert.AreEqual("ux.settings.update", r.Request); + + NonRequest n = JsonConvert.DeserializeObject(json); + Assert.AreEqual(new Guid("14c561bd-32a8-457e-b4e5-4bba0832897f"), n.Sid); + Assert.AreEqual(new Guid("30c39065-0f31-de11-9442-001e3786a8ec"), n.Uid); + Assert.AreEqual(8, n.FidOrder.Count); + Assert.AreEqual("id", n.FidOrder[0]); + Assert.AreEqual("titleId", n.FidOrder[n.FidOrder.Count - 1]); + } + +#if !SILVERLIGHT && !PocketPC && !NET20 + [MetadataType(typeof(OptInClassMetadata))] + public class OptInClass + { + [DataContract] + public class OptInClassMetadata + { + [DataMember] + public string Name { get; set; } + [DataMember] + public int Age { get; set; } + public string NotIncluded { get; set; } + } + + public string Name { get; set; } + public int Age { get; set; } + public string NotIncluded { get; set; } + } + + [Test] + public void OptInClassMetadataSerialization() + { + OptInClass optInClass = new OptInClass(); + optInClass.Age = 26; + optInClass.Name = "James NK"; + optInClass.NotIncluded = "Poor me :("; + + string json = JsonConvert.SerializeObject(optInClass, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Name"": ""James NK"", + ""Age"": 26 +}", json); + + OptInClass newOptInClass = JsonConvert.DeserializeObject(@"{ + ""Name"": ""James NK"", + ""NotIncluded"": ""Ignore me!"", + ""Age"": 26 +}"); + Assert.AreEqual(26, newOptInClass.Age); + Assert.AreEqual("James NK", newOptInClass.Name); + Assert.AreEqual(null, newOptInClass.NotIncluded); + } +#endif + +#if !PocketPC && !NET20 + [DataContract] + public class DataContractPrivateMembers + { + public DataContractPrivateMembers() + { + } + + public DataContractPrivateMembers(string name, int age, int rank, string title) + { + _name = name; + Age = age; + Rank = rank; + Title = title; + } + + [DataMember] + private string _name; + [DataMember(Name = "_age")] + private int Age { get; set; } + [JsonProperty] + private int Rank { get; set; } + [JsonProperty(PropertyName = "JsonTitle")] + [DataMember(Name = "DataTitle")] + private string Title { get; set; } + + public string NotIncluded { get; set; } + + public override string ToString() + { + return "_name: " + _name + ", _age: " + Age + ", Rank: " + Rank + ", JsonTitle: " + Title; + } + } + + [Test] + public void SerializeDataContractPrivateMembers() + { + DataContractPrivateMembers c = new DataContractPrivateMembers("Jeff", 26, 10, "Dr"); + c.NotIncluded = "Hi"; + string json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Assert.AreEqual(@"{ + ""_name"": ""Jeff"", + ""_age"": 26, + ""Rank"": 10, + ""JsonTitle"": ""Dr"" +}", json); + + DataContractPrivateMembers cc = JsonConvert.DeserializeObject(json); + Assert.AreEqual("_name: Jeff, _age: 26, Rank: 10, JsonTitle: Dr", cc.ToString()); + } +#endif + + [Test] + public void DeserializeDictionaryInterface() + { + string json = @"{ + ""Name"": ""Name!"", + ""Dictionary"": { + ""Item"": 11 + } +}"; + + DictionaryInterfaceClass c = JsonConvert.DeserializeObject(json, + new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace }); + Assert.AreEqual("Name!", c.Name); + Assert.AreEqual(1, c.Dictionary.Count); + Assert.AreEqual(11, c.Dictionary["Item"]); + } + + [Test] + public void DeserializeDictionaryInterfaceWithExistingValues() + { + string json = @"{ + ""Random"": { + ""blah"": 1 + }, + ""Name"": ""Name!"", + ""Dictionary"": { + ""Item"": 11, + ""Item1"": 12 + }, + ""Collection"": [ + 999 + ], + ""Employee"": { + ""Manager"": { + ""Name"": ""ManagerName!"" + } + } +}"; + + DictionaryInterfaceClass c = JsonConvert.DeserializeObject(json, + new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Reuse }); + + Assert.AreEqual("Name!", c.Name); + Assert.AreEqual(3, c.Dictionary.Count); + Assert.AreEqual(11, c.Dictionary["Item"]); + Assert.AreEqual(1, c.Dictionary["existing"]); + Assert.AreEqual(4, c.Collection.Count); + Assert.AreEqual(1, c.Collection.ElementAt(0)); + Assert.AreEqual(999, c.Collection.ElementAt(3)); + Assert.AreEqual("EmployeeName!", c.Employee.Name); + Assert.AreEqual("ManagerName!", c.Employee.Manager.Name); + Assert.IsNotNull(c.Random); + } + + [Test] + public void TypedObjectDeserializationWithComments() + { + string json = @"/*comment*/ { /*comment*/ + ""Name"": /*comment*/ ""Apple"" /*comment*/, /*comment*/ + ""ExpiryDate"": ""\/Date(1230422400000)\/"", + ""Price"": 3.99, + ""Sizes"": /*comment*/ [ /*comment*/ + ""Small"", /*comment*/ + ""Medium"" /*comment*/, + /*comment*/ ""Large"" + /*comment*/ ] /*comment*/ + } /*comment*/"; + + Product deserializedProduct = (Product)JsonConvert.DeserializeObject(json, typeof(Product)); + + Assert.AreEqual("Apple", deserializedProduct.Name); + Assert.AreEqual(new DateTime(2008, 12, 28, 0, 0, 0, DateTimeKind.Utc), deserializedProduct.ExpiryDate); + Assert.AreEqual(3.99, deserializedProduct.Price); + Assert.AreEqual("Small", deserializedProduct.Sizes[0]); + Assert.AreEqual("Medium", deserializedProduct.Sizes[1]); + Assert.AreEqual("Large", deserializedProduct.Sizes[2]); + } + + [Test] + public void NestedInsideOuterObject() + { + string json = @"{ + ""short"": { + ""original"": ""http://www.contrast.ie/blog/online-marketing-2009/"", + ""short"": ""m2sqc6"", + ""shortened"": ""http://short.ie/m2sqc6"", + ""error"": { + ""code"": 0, + ""msg"": ""No action taken"" + } + } +}"; + + JObject o = JObject.Parse(json); + + Shortie s = JsonConvert.DeserializeObject(o["short"].ToString()); + Assert.IsNotNull(s); + + Assert.AreEqual(s.Original, "http://www.contrast.ie/blog/online-marketing-2009/"); + Assert.AreEqual(s.Short, "m2sqc6"); + Assert.AreEqual(s.Shortened, "http://short.ie/m2sqc6"); + } + + [Test] + public void UriSerialization() + { + Uri uri = new Uri("http://codeplex.com"); + string json = JsonConvert.SerializeObject(uri); + + Assert.AreEqual("http://codeplex.com/", uri.ToString()); + + Uri newUri = JsonConvert.DeserializeObject(json); + Assert.AreEqual(uri, newUri); + } + + [Test] + public void AnonymousPlusLinqToSql() + { + var value = new + { + bar = new JObject(new JProperty("baz", 13)) + }; + + string json = JsonConvert.SerializeObject(value); + + Assert.AreEqual(@"{""bar"":{""baz"":13}}", json); + } + + [Test] + public void SerializeEnumerableAsObject() + { + Content content = new Content + { + Text = "Blah, blah, blah", + Children = new List + { + new Content { Text = "First" }, + new Content { Text = "Second" } + } + }; + + string json = JsonConvert.SerializeObject(content, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Children"": [ + { + ""Children"": null, + ""Text"": ""First"" + }, + { + ""Children"": null, + ""Text"": ""Second"" + } + ], + ""Text"": ""Blah, blah, blah"" +}", json); + } + + [Test] + public void DeserializeEnumerableAsObject() + { + string json = @"{ + ""Children"": [ + { + ""Children"": null, + ""Text"": ""First"" + }, + { + ""Children"": null, + ""Text"": ""Second"" + } + ], + ""Text"": ""Blah, blah, blah"" +}"; + + Content content = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("Blah, blah, blah", content.Text); + Assert.AreEqual(2, content.Children.Count); + Assert.AreEqual("First", content.Children[0].Text); + Assert.AreEqual("Second", content.Children[1].Text); + } + + [Test] + public void RoleTransferTest() + { + string json = @"{""Operation"":""1"",""RoleName"":""Admin"",""Direction"":""0""}"; + + RoleTransfer r = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(RoleTransferOperation.Second, r.Operation); + Assert.AreEqual("Admin", r.RoleName); + Assert.AreEqual(RoleTransferDirection.First, r.Direction); + } + + [Test] + public void PrimitiveValuesInObjectArray() + { + string json = @"{""action"":""Router"",""method"":""Navigate"",""data"":[""dashboard"",null],""type"":""rpc"",""tid"":2}"; + + ObjectArrayPropertyTest o = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("Router", o.Action); + Assert.AreEqual("Navigate", o.Method); + Assert.AreEqual(2, o.Data.Length); + Assert.AreEqual("dashboard", o.Data[0]); + Assert.AreEqual(null, o.Data[1]); + } + + [Test] + public void ComplexValuesInObjectArray() + { + string json = @"{""action"":""Router"",""method"":""Navigate"",""data"":[""dashboard"",[""id"", 1, ""teststring"", ""test""],{""one"":1}],""type"":""rpc"",""tid"":2}"; + + ObjectArrayPropertyTest o = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("Router", o.Action); + Assert.AreEqual("Navigate", o.Method); + Assert.AreEqual(3, o.Data.Length); + Assert.AreEqual("dashboard", o.Data[0]); + Assert.IsInstanceOfType(typeof(JArray), o.Data[1]); + Assert.AreEqual(4, ((JArray)o.Data[1]).Count); + Assert.IsInstanceOfType(typeof(JObject), o.Data[2]); + Assert.AreEqual(1, ((JObject)o.Data[2]).Count); + Assert.AreEqual(1, (int)((JObject)o.Data[2])["one"]); + } + + [Test] + public void DeserializeGenericDictionary() + { + string json = @"{""key1"":""value1"",""key2"":""value2""}"; + + Dictionary values = JsonConvert.DeserializeObject>(json); + + Console.WriteLine(values.Count); + // 2 + + Console.WriteLine(values["key1"]); + // value1 + + Assert.AreEqual(2, values.Count); + Assert.AreEqual("value1", values["key1"]); + Assert.AreEqual("value2", values["key2"]); + } + + [Test] + public void SerializeGenericList() + { + Product p1 = new Product + { + Name = "Product 1", + Price = 99.95m, + ExpiryDate = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc), + }; + Product p2 = new Product + { + Name = "Product 2", + Price = 12.50m, + ExpiryDate = new DateTime(2009, 7, 31, 0, 0, 0, DateTimeKind.Utc), + }; + + List products = new List(); + products.Add(p1); + products.Add(p2); + + string json = JsonConvert.SerializeObject(products, Formatting.Indented); + //[ + // { + // "Name": "Product 1", + // "ExpiryDate": "\/Date(978048000000)\/", + // "Price": 99.95, + // "Sizes": null + // }, + // { + // "Name": "Product 2", + // "ExpiryDate": "\/Date(1248998400000)\/", + // "Price": 12.50, + // "Sizes": null + // } + //] + + Assert.AreEqual(@"[ + { + ""Name"": ""Product 1"", + ""ExpiryDate"": ""\/Date(978048000000)\/"", + ""Price"": 99.95, + ""Sizes"": null + }, + { + ""Name"": ""Product 2"", + ""ExpiryDate"": ""\/Date(1248998400000)\/"", + ""Price"": 12.50, + ""Sizes"": null + } +]", json); + } + + [Test] + public void DeserializeGenericList() + { + string json = @"[ + { + ""Name"": ""Product 1"", + ""ExpiryDate"": ""\/Date(978048000000)\/"", + ""Price"": 99.95, + ""Sizes"": null + }, + { + ""Name"": ""Product 2"", + ""ExpiryDate"": ""\/Date(1248998400000)\/"", + ""Price"": 12.50, + ""Sizes"": null + } + ]"; + + List products = JsonConvert.DeserializeObject>(json); + + Console.WriteLine(products.Count); + // 2 + + Product p1 = products[0]; + + Console.WriteLine(p1.Name); + // Product 1 + + Assert.AreEqual(2, products.Count); + Assert.AreEqual("Product 1", products[0].Name); + } + +#if !PocketPC && !NET20 + [Test] + public void DeserializeEmptyStringToNullableDateTime() + { + string json = @"{""DateTimeField"":""""}"; + + NullableDateTimeTestClass c = JsonConvert.DeserializeObject(json); + Assert.AreEqual(null, c.DateTimeField); + } +#endif + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Unable to find a constructor to use for type Newtonsoft.Json.Tests.TestObjects.Event. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.")] + public void FailWhenClassWithNoDefaultConstructorHasMultipleConstructorsWithArguments() + { + string json = @"{""sublocation"":""AlertEmailSender.Program.Main"",""userId"":0,""type"":0,""summary"":""Loading settings variables"",""details"":null,""stackTrace"":"" at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)\r\n at System.Environment.get_StackTrace()\r\n at mr.Logging.Event..ctor(String summary) in C:\\Projects\\MRUtils\\Logging\\Event.vb:line 71\r\n at AlertEmailSender.Program.Main(String[] args) in C:\\Projects\\AlertEmailSender\\AlertEmailSender\\Program.cs:line 25"",""tag"":null,""time"":""\/Date(1249591032026-0400)\/""}"; + + Event e = JsonConvert.DeserializeObject(json); + } + + [Test] + public void DeserializeObjectSetOnlyProperty() + { + string json = @"{'SetOnlyProperty':[1,2,3,4,5]}"; + + SetOnlyPropertyClass2 setOnly = JsonConvert.DeserializeObject(json); + JArray a = (JArray)setOnly.GetValue(); + Assert.AreEqual(5, a.Count); + Assert.AreEqual(1, (int)a[0]); + Assert.AreEqual(5, (int)a[a.Count - 1]); + } + + [Test] + public void DeserializeOptInClasses() + { + string json = @"{id: ""12"", name: ""test"", items: [{id: ""112"", name: ""testing""}]}"; + + ListTestClass l = JsonConvert.DeserializeObject(json); + } + + [Test] + public void DeserializeNullableListWithNulls() + { + List l = JsonConvert.DeserializeObject>("[ 3.3, null, 1.1 ] "); + Assert.AreEqual(3, l.Count); + + Assert.AreEqual(3.3m, l[0]); + Assert.AreEqual(null, l[1]); + Assert.AreEqual(1.1m, l[2]); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Cannot deserialize JSON array into type 'Newtonsoft.Json.Tests.TestObjects.Person'.")] + public void CannotDeserializeArrayIntoObject() + { + string json = @"[]"; + + JsonConvert.DeserializeObject(json); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Cannot deserialize JSON object into type 'System.Collections.Generic.List`1[Newtonsoft.Json.Tests.TestObjects.Person]'.")] + public void CannotDeserializeObjectIntoArray() + { + string json = @"{}"; + + JsonConvert.DeserializeObject>(json); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Cannot populate JSON array onto type 'Newtonsoft.Json.Tests.TestObjects.Person'.")] + public void CannotPopulateArrayIntoObject() + { + string json = @"[]"; + + JsonConvert.PopulateObject(json, new Person()); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Cannot populate JSON object onto type 'System.Collections.Generic.List`1[Newtonsoft.Json.Tests.TestObjects.Person]'.")] + public void CannotPopulateObjectIntoArray() + { + string json = @"{}"; + + JsonConvert.PopulateObject(json, new List()); + } + + [Test] + public void DeserializeEmptyString() + { + string json = @"{""Name"":""""}"; + + Person p = JsonConvert.DeserializeObject(json); + Assert.AreEqual("", p.Name); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error getting value from 'ReadTimeout' on 'System.IO.MemoryStream'.")] + public void SerializePropertyGetError() + { + JsonConvert.SerializeObject(new MemoryStream()); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error setting value to 'ReadTimeout' on 'System.IO.MemoryStream'.")] + public void DeserializePropertySetError() + { + JsonConvert.DeserializeObject("{ReadTimeout:0}"); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error converting value """" to type 'System.Int32'.")] + public void DeserializeEnsureTypeEmptyStringToIntError() + { + JsonConvert.DeserializeObject("{ReadTimeout:''}"); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error converting value {null} to type 'System.Int32'.")] + public void DeserializeEnsureTypeNullToIntError() + { + JsonConvert.DeserializeObject("{ReadTimeout:null}"); + } + + [Test] + public void SerializeGenericListOfStrings() + { + List strings = new List(); + + strings.Add("str_1"); + strings.Add("str_2"); + strings.Add("str_3"); + + string json = JsonConvert.SerializeObject(strings); + Assert.AreEqual(@"[""str_1"",""str_2"",""str_3""]", json); + } + + [Test] + public void ConstructorReadonlyFieldsTest() + { + ConstructorReadonlyFields c1 = new ConstructorReadonlyFields("String!", int.MaxValue); + string json = JsonConvert.SerializeObject(c1, Formatting.Indented); + Assert.AreEqual(@"{ + ""A"": ""String!"", + ""B"": 2147483647 +}", json); + + ConstructorReadonlyFields c2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual("String!", c2.A); + Assert.AreEqual(int.MaxValue, c2.B); + } + + [Test] + public void SerializeStruct() + { + StructTest structTest = new StructTest + { + StringProperty = "StringProperty!", + StringField = "StringField", + IntProperty = 5, + IntField = 10 + }; + + string json = JsonConvert.SerializeObject(structTest, Formatting.Indented); + Console.WriteLine(json); + Assert.AreEqual(@"{ + ""StringField"": ""StringField"", + ""IntField"": 10, + ""StringProperty"": ""StringProperty!"", + ""IntProperty"": 5 +}", json); + + StructTest deserialized = JsonConvert.DeserializeObject(json); + Assert.AreEqual(structTest.StringProperty, deserialized.StringProperty); + Assert.AreEqual(structTest.StringField, deserialized.StringField); + Assert.AreEqual(structTest.IntProperty, deserialized.IntProperty); + Assert.AreEqual(structTest.IntField, deserialized.IntField); + } + + [Test] + public void SerializeListWithJsonConverter() + { + Foo f = new Foo(); + f.Bars.Add(new Bar { Id = 0 }); + f.Bars.Add(new Bar { Id = 1 }); + f.Bars.Add(new Bar { Id = 2 }); + + string json = JsonConvert.SerializeObject(f, Formatting.Indented); + Assert.AreEqual(@"{ + ""Bars"": [ + 0, + 1, + 2 + ] +}", json); + + Foo newFoo = JsonConvert.DeserializeObject(json); + Assert.AreEqual(3, newFoo.Bars.Count); + Assert.AreEqual(0, newFoo.Bars[0].Id); + Assert.AreEqual(1, newFoo.Bars[1].Id); + Assert.AreEqual(2, newFoo.Bars[2].Id); + } + + [Test] + public void SerializeGuidKeyedDictionary() + { + Dictionary dictionary = new Dictionary(); + dictionary.Add(new Guid("F60EAEE0-AE47-488E-B330-59527B742D77"), 1); + dictionary.Add(new Guid("C2594C02-EBA1-426A-AA87-8DD8871350B0"), 2); + + string json = JsonConvert.SerializeObject(dictionary, Formatting.Indented); + Assert.AreEqual(@"{ + ""f60eaee0-ae47-488e-b330-59527b742d77"": 1, + ""c2594c02-eba1-426a-aa87-8dd8871350b0"": 2 +}", json); + } + + [Test] + public void SerializePersonKeyedDictionary() + { + Dictionary dictionary = new Dictionary(); + dictionary.Add(new Person { Name = "p1" }, 1); + dictionary.Add(new Person { Name = "p2" }, 2); + + string json = JsonConvert.SerializeObject(dictionary, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Newtonsoft.Json.Tests.TestObjects.Person"": 1, + ""Newtonsoft.Json.Tests.TestObjects.Person"": 2 +}", json); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Could not convert string 'Newtonsoft.Json.Tests.TestObjects.Person' to dictionary key type 'Newtonsoft.Json.Tests.TestObjects.Person'. Create a TypeConverter to convert from the string to the key type object.")] + public void DeserializePersonKeyedDictionary() + { + string json = + @"{ + ""Newtonsoft.Json.Tests.TestObjects.Person"": 1, + ""Newtonsoft.Json.Tests.TestObjects.Person"": 2 +}"; + + JsonConvert.DeserializeObject>(json); + } + + [Test] + public void SerializeFragment() + { + string googleSearchText = @"{ + ""responseData"": { + ""results"": [ + { + ""GsearchResultClass"": ""GwebSearch"", + ""unescapedUrl"": ""http://en.wikipedia.org/wiki/Paris_Hilton"", + ""url"": ""http://en.wikipedia.org/wiki/Paris_Hilton"", + ""visibleUrl"": ""en.wikipedia.org"", + ""cacheUrl"": ""http://www.google.com/search?q=cache:TwrPfhd22hYJ:en.wikipedia.org"", + ""title"": ""Paris Hilton - Wikipedia, the free encyclopedia"", + ""titleNoFormatting"": ""Paris Hilton - Wikipedia, the free encyclopedia"", + ""content"": ""[1] In 2006, she released her debut album..."" + }, + { + ""GsearchResultClass"": ""GwebSearch"", + ""unescapedUrl"": ""http://www.imdb.com/name/nm0385296/"", + ""url"": ""http://www.imdb.com/name/nm0385296/"", + ""visibleUrl"": ""www.imdb.com"", + ""cacheUrl"": ""http://www.google.com/search?q=cache:1i34KkqnsooJ:www.imdb.com"", + ""title"": ""Paris Hilton"", + ""titleNoFormatting"": ""Paris Hilton"", + ""content"": ""Self: Zoolander. Socialite Paris Hilton..."" + } + ], + ""cursor"": { + ""pages"": [ + { + ""start"": ""0"", + ""label"": 1 + }, + { + ""start"": ""4"", + ""label"": 2 + }, + { + ""start"": ""8"", + ""label"": 3 + }, + { + ""start"": ""12"", + ""label"": 4 + } + ], + ""estimatedResultCount"": ""59600000"", + ""currentPageIndex"": 0, + ""moreResultsUrl"": ""http://www.google.com/search?oe=utf8&ie=utf8..."" + } + }, + ""responseDetails"": null, + ""responseStatus"": 200 + }"; + + JObject googleSearch = JObject.Parse(googleSearchText); + + // get JSON result objects into a list + IList results = googleSearch["responseData"]["results"].Children().ToList(); + + // serialize JSON results into .NET objects + IList searchResults = new List(); + foreach (JToken result in results) + { + SearchResult searchResult = JsonConvert.DeserializeObject(result.ToString()); + searchResults.Add(searchResult); + } + + // Title = Paris Hilton - Wikipedia, the free encyclopedia + // Content = [1] In 2006, she released her debut album... + // Url = http://en.wikipedia.org/wiki/Paris_Hilton + + // Title = Paris Hilton + // Content = Self: Zoolander. Socialite Paris Hilton... + // Url = http://www.imdb.com/name/nm0385296/ + + Assert.AreEqual(2, searchResults.Count); + Assert.AreEqual("Paris Hilton - Wikipedia, the free encyclopedia", searchResults[0].Title); + Assert.AreEqual("Paris Hilton", searchResults[1].Title); + } + + [Test] + public void DeserializeBaseReferenceWithDerivedValue() + { + PersonPropertyClass personPropertyClass = new PersonPropertyClass(); + WagePerson wagePerson = (WagePerson)personPropertyClass.Person; + + wagePerson.BirthDate = new DateTime(2000, 11, 29, 23, 59, 59, DateTimeKind.Utc); + wagePerson.Department = "McDees"; + wagePerson.HourlyWage = 12.50m; + wagePerson.LastModified = new DateTime(2000, 11, 29, 23, 59, 59, DateTimeKind.Utc); + wagePerson.Name = "Jim Bob"; + + string json = JsonConvert.SerializeObject(personPropertyClass, Formatting.Indented); + Assert.AreEqual( + @"{ + ""Person"": { + ""HourlyWage"": 12.50, + ""Name"": ""Jim Bob"", + ""BirthDate"": ""\/Date(975542399000)\/"", + ""LastModified"": ""\/Date(975542399000)\/"" + } +}", + json); + + PersonPropertyClass newPersonPropertyClass = JsonConvert.DeserializeObject(json); + Assert.AreEqual(wagePerson.HourlyWage, ((WagePerson)newPersonPropertyClass.Person).HourlyWage); + } + + public class ExistingValueClass + { + public Dictionary Dictionary { get; set; } + public List List { get; set; } + + public ExistingValueClass() + { + Dictionary = new Dictionary + { + {"existing", "yup"} + }; + List = new List + { + "existing" + }; + } + } + + [Test] + public void DeserializePopulateDictionaryAndList() + { + ExistingValueClass d = JsonConvert.DeserializeObject(@"{'Dictionary':{appended:'appended',existing:'new'}}"); + + Assert.IsNotNull(d); + Assert.IsNotNull(d.Dictionary); + Assert.AreEqual(typeof(Dictionary), d.Dictionary.GetType()); + Assert.AreEqual(typeof(List), d.List.GetType()); + Assert.AreEqual(2, d.Dictionary.Count); + Assert.AreEqual("new", d.Dictionary["existing"]); + Assert.AreEqual("appended", d.Dictionary["appended"]); + Assert.AreEqual(1, d.List.Count); + Assert.AreEqual("existing", d.List[0]); + } + + public interface IKeyValueId + { + int Id { get; set; } + string Key { get; set; } + string Value { get; set; } + } + + + public class KeyValueId : IKeyValueId + { + public int Id { get; set; } + public string Key { get; set; } + public string Value { get; set; } + } + + public class ThisGenericTest where T : IKeyValueId + { + private Dictionary _dict1 = new Dictionary(); + + public string MyProperty { get; set; } + + public void Add(T item) + { + this._dict1.Add(item.Key, item); + } + + public T this[string key] + { + get { return this._dict1[key]; } + set { this._dict1[key] = value; } + } + + public T this[int id] + { + get { return this._dict1.Values.FirstOrDefault(x => x.Id == id); } + set + { + var item = this[id]; + + if (item == null) + this.Add(value); + else + this._dict1[item.Key] = value; + } + } + + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + public T[] TheItems + { + get { return this._dict1.Values.ToArray(); } + set + { + foreach (var item in value) + this.Add(item); + } + } + } + + [Test] + public void IgnoreIndexedProperties() + { + ThisGenericTest g = new ThisGenericTest(); + + g.Add(new KeyValueId { Id = 1, Key = "key1", Value = "value1" }); + g.Add(new KeyValueId { Id = 2, Key = "key2", Value = "value2" }); + + g.MyProperty = "some value"; + + string json = g.ToJson(); + + Assert.AreEqual(@"{ + ""MyProperty"": ""some value"", + ""TheItems"": [ + { + ""Id"": 1, + ""Key"": ""key1"", + ""Value"": ""value1"" + }, + { + ""Id"": 2, + ""Key"": ""key2"", + ""Value"": ""value2"" + } + ] +}", json); + + ThisGenericTest gen = JsonConvert.DeserializeObject>(json); + Assert.AreEqual("some value", gen.MyProperty); + } + + public class JRawValueTestObject + { + public JRaw Value { get; set; } + } + + [Test] + public void JRawValue() + { + JRawValueTestObject deserialized = JsonConvert.DeserializeObject("{value:3}"); + Assert.AreEqual("3", deserialized.Value.ToString()); + + deserialized = JsonConvert.DeserializeObject("{value:'3'}"); + Assert.AreEqual(@"""3""", deserialized.Value.ToString()); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Unable to find a default constructor to use for type Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+DictionaryWithNoDefaultConstructor.")] + public void DeserializeDictionaryWithNoDefaultConstructor() + { + string json = "{key1:'value',key2:'value',key3:'value'}"; + JsonConvert.DeserializeObject(json); + } + + public class DictionaryWithNoDefaultConstructor : Dictionary + { + public DictionaryWithNoDefaultConstructor(IEnumerable> initial) + { + foreach (KeyValuePair pair in initial) + { + Add(pair.Key, pair.Value); + } + } + } + + [JsonObject(MemberSerialization.OptIn)] + public class A + { + [JsonProperty("A1")] + private string _A1; + public string A1 { get { return _A1; } set { _A1 = value; } } + + [JsonProperty("A2")] + private string A2 { get; set; } + } + + [JsonObject(MemberSerialization.OptIn)] + public class B : A + { + public string B1 { get; set; } + + [JsonProperty("B2")] + string _B2; + public string B2 { get { return _B2; } set { _B2 = value; } } + + [JsonProperty("B3")] + private string B3 { get; set; } + } + + [Test] + public void SerializeNonPublicBaseJsonProperties() + { + B value = new B(); + string json = JsonConvert.SerializeObject(value, Formatting.Indented); + + Assert.AreEqual(@"{ + ""B2"": null, + ""A1"": null, + ""B3"": null, + ""A2"": null +}", json); + } + + public class TestClass + { + public string Key { get; set; } + public object Value { get; set; } + } + + [Test] + public void DeserializeToObjectProperty() + { + var json = "{ Key: 'abc', Value: 123 }"; + var item = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(123, item.Value); + } + + public abstract class Animal + { + public abstract string Name { get; } + } + + public class Human : Animal + { + public override string Name + { + get { return typeof(Human).Name; } + } + + public string Ethnicity { get; set; } + } + +#if !NET20 && !PocketPC && !WINDOWS_PHONE + public class DataContractJsonSerializerTestClass + { + public TimeSpan TimeSpanProperty { get; set; } + public Guid GuidProperty { get; set; } + public Animal AnimalProperty { get; set; } + public Exception ExceptionProperty { get; set; } + } + + [Test] + public void DataContractJsonSerializerTest() + { + Exception ex = new Exception("Blah blah blah"); + + DataContractJsonSerializerTestClass c = new DataContractJsonSerializerTestClass(); + c.TimeSpanProperty = new TimeSpan(200, 20, 59, 30, 900); + c.GuidProperty = new Guid("66143115-BE2A-4a59-AF0A-348E1EA15B1E"); + c.AnimalProperty = new Human() { Ethnicity = "European" }; + c.ExceptionProperty = ex; + + MemoryStream ms = new MemoryStream(); + DataContractJsonSerializer serializer = new DataContractJsonSerializer( + typeof(DataContractJsonSerializerTestClass), + new Type[] { typeof(Human) }); + serializer.WriteObject(ms, c); + + byte[] jsonBytes = ms.ToArray(); + string json = Encoding.UTF8.GetString(jsonBytes, 0, jsonBytes.Length); + + Console.WriteLine(JObject.Parse(json).ToString()); + Console.WriteLine(); + + Console.WriteLine(JsonConvert.SerializeObject(c, Formatting.Indented, new JsonSerializerSettings + { + // TypeNameHandling = TypeNameHandling.Objects + })); + } +#endif + + public class ModelStateDictionary : IDictionary + { + + private readonly Dictionary _innerDictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); + + public ModelStateDictionary() + { + } + + public ModelStateDictionary(ModelStateDictionary dictionary) + { + if (dictionary == null) + { + throw new ArgumentNullException("dictionary"); + } + + foreach (var entry in dictionary) + { + _innerDictionary.Add(entry.Key, entry.Value); + } + } + + public int Count + { + get + { + return _innerDictionary.Count; + } + } + + public bool IsReadOnly + { + get + { + return ((IDictionary)_innerDictionary).IsReadOnly; + } + } + + public ICollection Keys + { + get + { + return _innerDictionary.Keys; + } + } + + public T this[string key] + { + get + { + T value; + _innerDictionary.TryGetValue(key, out value); + return value; + } + set + { + _innerDictionary[key] = value; + } + } + + public ICollection Values + { + get + { + return _innerDictionary.Values; + } + } + + public void Add(KeyValuePair item) + { + ((IDictionary)_innerDictionary).Add(item); + } + + public void Add(string key, T value) + { + _innerDictionary.Add(key, value); + } + + public void Clear() + { + _innerDictionary.Clear(); + } + + public bool Contains(KeyValuePair item) + { + return ((IDictionary)_innerDictionary).Contains(item); + } + + public bool ContainsKey(string key) + { + return _innerDictionary.ContainsKey(key); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + ((IDictionary)_innerDictionary).CopyTo(array, arrayIndex); + } + + public IEnumerator> GetEnumerator() + { + return _innerDictionary.GetEnumerator(); + } + + public void Merge(ModelStateDictionary dictionary) + { + if (dictionary == null) + { + return; + } + + foreach (var entry in dictionary) + { + this[entry.Key] = entry.Value; + } + } + + public bool Remove(KeyValuePair item) + { + return ((IDictionary)_innerDictionary).Remove(item); + } + + public bool Remove(string key) + { + return _innerDictionary.Remove(key); + } + + public bool TryGetValue(string key, out T value) + { + return _innerDictionary.TryGetValue(key, out value); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_innerDictionary).GetEnumerator(); + } + } + + [Test] + public void SerializeNonIDictionary() + { + ModelStateDictionary modelStateDictionary = new ModelStateDictionary(); + modelStateDictionary.Add("key", "value"); + + string json = JsonConvert.SerializeObject(modelStateDictionary); + + Assert.AreEqual(@"{""key"":""value""}", json); + + ModelStateDictionary newModelStateDictionary = JsonConvert.DeserializeObject>(json); + Assert.AreEqual(1, newModelStateDictionary.Count); + Assert.AreEqual("value", newModelStateDictionary["key"]); + } + +#if !SILVERLIGHT && !PocketPC + public class ISerializableTestObject : ISerializable + { + internal string _stringValue; + internal int _intValue; + internal DateTimeOffset _dateTimeOffsetValue; + internal Person _personValue; + internal Person _nullPersonValue; + internal int? _nullableInt; + internal bool _booleanValue; + internal byte _byteValue; + internal char _charValue; + internal DateTime _dateTimeValue; + internal decimal _decimalValue; + internal short _shortValue; + internal long _longValue; + internal sbyte _sbyteValue; + internal float _floatValue; + internal ushort _ushortValue; + internal uint _uintValue; + internal ulong _ulongValue; + + public ISerializableTestObject(string stringValue, int intValue, DateTimeOffset dateTimeOffset, Person personValue) + { + _stringValue = stringValue; + _intValue = intValue; + _dateTimeOffsetValue = dateTimeOffset; + _personValue = personValue; + _dateTimeValue = new DateTime(0, DateTimeKind.Utc); + } + + protected ISerializableTestObject(SerializationInfo info, StreamingContext context) + { + _stringValue = info.GetString("stringValue"); + _intValue = info.GetInt32("intValue"); + _dateTimeOffsetValue = (DateTimeOffset)info.GetValue("dateTimeOffsetValue", typeof(DateTimeOffset)); + _personValue = (Person)info.GetValue("personValue", typeof(Person)); + _nullPersonValue = (Person)info.GetValue("nullPersonValue", typeof(Person)); + _nullableInt = (int?)info.GetValue("nullableInt", typeof(int?)); + + _booleanValue = info.GetBoolean("booleanValue"); + _byteValue = info.GetByte("byteValue"); + _charValue = info.GetChar("charValue"); + _dateTimeValue = info.GetDateTime("dateTimeValue"); + _decimalValue = info.GetDecimal("decimalValue"); + _shortValue = info.GetInt16("shortValue"); + _longValue = info.GetInt64("longValue"); + _sbyteValue = info.GetSByte("sbyteValue"); + _floatValue = info.GetSingle("floatValue"); + _ushortValue = info.GetUInt16("ushortValue"); + _uintValue = info.GetUInt32("uintValue"); + _ulongValue = info.GetUInt64("ulongValue"); + } + + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("stringValue", _stringValue); + info.AddValue("intValue", _intValue); + info.AddValue("dateTimeOffsetValue", _dateTimeOffsetValue); + info.AddValue("personValue", _personValue); + info.AddValue("nullPersonValue", _nullPersonValue); + info.AddValue("nullableInt", null); + + info.AddValue("booleanValue", _booleanValue); + info.AddValue("byteValue", _byteValue); + info.AddValue("charValue", _charValue); + info.AddValue("dateTimeValue", _dateTimeValue); + info.AddValue("decimalValue", _decimalValue); + info.AddValue("shortValue", _shortValue); + info.AddValue("longValue", _longValue); + info.AddValue("sbyteValue", _sbyteValue); + info.AddValue("floatValue", _floatValue); + info.AddValue("ushortValue", _ushortValue); + info.AddValue("uintValue", _uintValue); + info.AddValue("ulongValue", _ulongValue); + } + } + + [Test] + public void SerializeISerializableTestObject() + { + Person person = new Person(); + person.BirthDate = new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc); + person.LastModified = person.BirthDate; + person.Department = "Department!"; + person.Name = "Name!"; + + DateTimeOffset dateTimeOffset = new DateTimeOffset(2000, 12, 20, 22, 59, 59, TimeSpan.FromHours(2)); + string dateTimeOffsetText; +#if !NET20 + dateTimeOffsetText = @"\/Date(977345999000+0200)\/"; +#else + dateTimeOffsetText = @"12/20/2000 22:59:59 +02:00"; +#endif + + ISerializableTestObject o = new ISerializableTestObject("String!", int.MinValue, dateTimeOffset, person); + + string json = JsonConvert.SerializeObject(o, Formatting.Indented); + Assert.AreEqual(@"{ + ""stringValue"": ""String!"", + ""intValue"": -2147483648, + ""dateTimeOffsetValue"": """ + dateTimeOffsetText + @""", + ""personValue"": { + ""Name"": ""Name!"", + ""BirthDate"": ""\/Date(946688461000)\/"", + ""LastModified"": ""\/Date(946688461000)\/"" + }, + ""nullPersonValue"": null, + ""nullableInt"": null, + ""booleanValue"": false, + ""byteValue"": 0, + ""charValue"": ""\u0000"", + ""dateTimeValue"": ""\/Date(-62135596800000)\/"", + ""decimalValue"": 0.0, + ""shortValue"": 0, + ""longValue"": 0, + ""sbyteValue"": 0, + ""floatValue"": 0.0, + ""ushortValue"": 0, + ""uintValue"": 0, + ""ulongValue"": 0 +}", json); + + ISerializableTestObject o2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual("String!", o2._stringValue); + Assert.AreEqual(int.MinValue, o2._intValue); + Assert.AreEqual(dateTimeOffset, o2._dateTimeOffsetValue); + Assert.AreEqual("Name!", o2._personValue.Name); + Assert.AreEqual(null, o2._nullPersonValue); + Assert.AreEqual(null, o2._nullableInt); + } +#endif + + public class KVPair + { + public TKey Key { get; set; } + public TValue Value { get; set; } + + public KVPair(TKey k, TValue v) + { + Key = k; + Value = v; + } + } + + [Test] + public void DeserializeUsingNonDefaultConstructorWithLeftOverValues() + { + List> kvPairs = + JsonConvert.DeserializeObject>>( + "[{\"Key\":\"Two\",\"Value\":\"2\"},{\"Key\":\"One\",\"Value\":\"1\"}]"); + + Assert.AreEqual(2, kvPairs.Count); + Assert.AreEqual("Two", kvPairs[0].Key); + Assert.AreEqual("2", kvPairs[0].Value); + Assert.AreEqual("One", kvPairs[1].Key); + Assert.AreEqual("1", kvPairs[1].Value); + } + + [Test] + public void SerializeClassWithInheritedProtectedMember() + { + AA myA = new AA(2); + string json = JsonConvert.SerializeObject(myA, Formatting.Indented); + Assert.AreEqual(@"{ + ""AA_field1"": 2, + ""AA_property1"": 2, + ""AA_property2"": 2, + ""AA_property3"": 2, + ""AA_property4"": 2 +}", json); + + BB myB = new BB(3, 4); + json = JsonConvert.SerializeObject(myB, Formatting.Indented); + Assert.AreEqual(@"{ + ""BB_field1"": 4, + ""BB_field2"": 4, + ""AA_field1"": 3, + ""BB_property1"": 4, + ""BB_property2"": 4, + ""BB_property3"": 4, + ""BB_property4"": 4, + ""BB_property5"": 4, + ""BB_property7"": 4, + ""AA_property1"": 3, + ""AA_property2"": 3, + ""AA_property3"": 3, + ""AA_property4"": 3 +}", json); + } + + [Test] + public void DeserializeClassWithInheritedProtectedMember() + { + AA myA = JsonConvert.DeserializeObject( + @"{ + ""AA_field1"": 2, + ""AA_field2"": 2, + ""AA_property1"": 2, + ""AA_property2"": 2, + ""AA_property3"": 2, + ""AA_property4"": 2, + ""AA_property5"": 2, + ""AA_property6"": 2 +}"); + + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetField("AA_field1", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetField("AA_field2", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property1", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property2", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property3", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property4", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property5", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property6", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + + BB myB = JsonConvert.DeserializeObject( + @"{ + ""BB_field1"": 4, + ""BB_field2"": 4, + ""AA_field1"": 3, + ""AA_field2"": 3, + ""AA_property1"": 2, + ""AA_property2"": 2, + ""AA_property3"": 2, + ""AA_property4"": 2, + ""AA_property5"": 2, + ""AA_property6"": 2, + ""BB_property1"": 3, + ""BB_property2"": 3, + ""BB_property3"": 3, + ""BB_property4"": 3, + ""BB_property5"": 3, + ""BB_property6"": 3, + ""BB_property7"": 3, + ""BB_property8"": 3 +}"); + + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(AA).GetField("AA_field1", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetField("AA_field2", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property1", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property2", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property3", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property4", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property5", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property6", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + + Assert.AreEqual(4, myB.BB_field1); + Assert.AreEqual(4, myB.BB_field2); + Assert.AreEqual(3, myB.BB_property1); + Assert.AreEqual(3, myB.BB_property2); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property3", BindingFlags.Instance | BindingFlags.Public), myB)); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property4", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(0, myB.BB_property5); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property6", BindingFlags.Instance | BindingFlags.Public), myB)); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property7", BindingFlags.Instance | BindingFlags.Public), myB)); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property8", BindingFlags.Instance | BindingFlags.Public), myB)); + } + + public class AA + { + [JsonProperty] + protected int AA_field1; + protected int AA_field2; + [JsonProperty] + protected int AA_property1 { get; set; } + [JsonProperty] + protected int AA_property2 { get; private set; } + [JsonProperty] + protected int AA_property3 { private get; set; } + [JsonProperty] + private int AA_property4 { get; set; } + protected int AA_property5 { get; private set; } + protected int AA_property6 { private get; set; } + + public AA() + { + } + + public AA(int f) + { + AA_field1 = f; + AA_field2 = f; + AA_property1 = f; + AA_property2 = f; + AA_property3 = f; + AA_property4 = f; + AA_property5 = f; + AA_property6 = f; + } + } + + public class BB : AA + { + [JsonProperty] + public int BB_field1; + public int BB_field2; + [JsonProperty] + public int BB_property1 { get; set; } + [JsonProperty] + public int BB_property2 { get; private set; } + [JsonProperty] + public int BB_property3 { private get; set; } + [JsonProperty] + private int BB_property4 { get; set; } + public int BB_property5 { get; private set; } + public int BB_property6 { private get; set; } + [JsonProperty] + public int BB_property7 { protected get; set; } + public int BB_property8 { protected get; set; } + + public BB() + { + } + + public BB(int f, int g) + : base(f) + { + BB_field1 = g; + BB_field2 = g; + BB_property1 = g; + BB_property2 = g; + BB_property3 = g; + BB_property4 = g; + BB_property5 = g; + BB_property6 = g; + BB_property7 = g; + BB_property8 = g; + } + } + +#if !NET20 && !SILVERLIGHT + public class XNodeTestObject + { + public XDocument Document { get; set; } + public XElement Element { get; set; } + } +#endif + +#if !SILVERLIGHT + public class XmlNodeTestObject + { + public XmlDocument Document { get; set; } + } +#endif + +#if !NET20 && !SILVERLIGHT + [Test] + public void SerializeDeserializeXNodeProperties() + { + XNodeTestObject testObject = new XNodeTestObject(); + testObject.Document = XDocument.Parse("hehe, root"); + testObject.Element = XElement.Parse(@"element"); + + string json = JsonConvert.SerializeObject(testObject, Formatting.Indented); + string expected = @"{ + ""Document"": { + ""root"": ""hehe, root"" + }, + ""Element"": { + ""fifth"": { + ""@xmlns:json"": ""http://json.org"", + ""@json:Awesome"": ""true"", + ""#text"": ""element"" + } + } +}"; + Assert.AreEqual(expected, json); + + XNodeTestObject newTestObject = JsonConvert.DeserializeObject(json); + Assert.AreEqual(testObject.Document.ToString(), newTestObject.Document.ToString()); + Assert.AreEqual(testObject.Element.ToString(), newTestObject.Element.ToString()); + + Assert.IsNull(newTestObject.Element.Parent); + } +#endif + +#if !SILVERLIGHT + [Test] + public void SerializeDeserializeXmlNodeProperties() + { + XmlNodeTestObject testObject = new XmlNodeTestObject(); + XmlDocument document = new XmlDocument(); + document.LoadXml("hehe, root"); + testObject.Document = document; + + string json = JsonConvert.SerializeObject(testObject, Formatting.Indented); + string expected = @"{ + ""Document"": { + ""root"": ""hehe, root"" + } +}"; + Assert.AreEqual(expected, json); + + XmlNodeTestObject newTestObject = JsonConvert.DeserializeObject(json); + Assert.AreEqual(testObject.Document.InnerXml, newTestObject.Document.InnerXml); + } +#endif + + [Test] + public void FullClientMapSerialization() + { + ClientMap source = new ClientMap() + { + position = new Pos() { X = 100, Y = 200 }, + center = new PosDouble() { X = 251.6, Y = 361.3 } + }; + + string json = JsonConvert.SerializeObject(source, new PosConverter(), new PosDoubleConverter()); + Assert.AreEqual("{\"position\":new Pos(100,200),\"center\":new PosD(251.6,361.3)}", json); + } + + public class ClientMap + { + public Pos position { get; set; } + public PosDouble center { get; set; } + } + + public class Pos + { + public int X { get; set; } + public int Y { get; set; } + } + + public class PosDouble + { + public double X { get; set; } + public double Y { get; set; } + } + + public class PosConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + Pos p = (Pos)value; + + if (p != null) + writer.WriteRawValue(String.Format("new Pos({0},{1})", p.X, p.Y)); + else + writer.WriteNull(); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override bool CanConvert(Type objectType) + { + return objectType.IsAssignableFrom(typeof(Pos)); + } + } + + public class PosDoubleConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + PosDouble p = (PosDouble)value; + + if (p != null) + writer.WriteRawValue(String.Format(CultureInfo.InvariantCulture, "new PosD({0},{1})", p.X, p.Y)); + else + writer.WriteNull(); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override bool CanConvert(Type objectType) + { + return objectType.IsAssignableFrom(typeof(PosDouble)); + } + } + + [Test] + public void TestEscapeDictionaryStrings() + { + const string s = @"host\user"; + string serialized = JsonConvert.SerializeObject(s); + Assert.AreEqual(@"""host\\user""", serialized); + + Dictionary d1 = new Dictionary(); + d1.Add(5, s); + Assert.AreEqual(@"{""5"":""host\\user""}", JsonConvert.SerializeObject(d1)); + + Dictionary d2 = new Dictionary(); + d2.Add(s, 5); + Assert.AreEqual(@"{""host\\user"":5}", JsonConvert.SerializeObject(d2)); + } + + public class GenericListTestClass + { + public List GenericList { get; set; } + + public GenericListTestClass() + { + GenericList = new List(); + } + } + + [Test] + public void DeserializeExistingGenericList() + { + GenericListTestClass c = new GenericListTestClass(); + c.GenericList.Add("1"); + c.GenericList.Add("2"); + + string json = JsonConvert.SerializeObject(c, Formatting.Indented); + + GenericListTestClass newValue = JsonConvert.DeserializeObject(json); + Assert.AreEqual(2, newValue.GenericList.Count); + Assert.AreEqual(typeof(List), newValue.GenericList.GetType()); + } + + [Test] + public void DeserializeSimpleKeyValuePair() + { + List> list = new List>(); + list.Add(new KeyValuePair("key1", "value1")); + list.Add(new KeyValuePair("key2", "value2")); + + string json = JsonConvert.SerializeObject(list); + + Assert.AreEqual(@"[{""Key"":""key1"",""Value"":""value1""},{""Key"":""key2"",""Value"":""value2""}]", json); + + List> result = JsonConvert.DeserializeObject>>(json); + Assert.AreEqual(2, result.Count); + Assert.AreEqual("key1", result[0].Key); + Assert.AreEqual("value1", result[0].Value); + Assert.AreEqual("key2", result[1].Key); + Assert.AreEqual("value2", result[1].Value); + } + + [Test] + public void DeserializeComplexKeyValuePair() + { + DateTime dateTime = new DateTime(2000, 12, 1, 23, 1, 1, DateTimeKind.Utc); + + List> list = new List>(); + list.Add(new KeyValuePair("key1", new WagePerson + { + BirthDate = dateTime, + Department = "Department1", + LastModified = dateTime, + HourlyWage = 1 + })); + list.Add(new KeyValuePair("key2", new WagePerson + { + BirthDate = dateTime, + Department = "Department2", + LastModified = dateTime, + HourlyWage = 2 + })); + + string json = JsonConvert.SerializeObject(list, Formatting.Indented); + + Assert.AreEqual(@"[ + { + ""Key"": ""key1"", + ""Value"": { + ""HourlyWage"": 1.0, + ""Name"": null, + ""BirthDate"": ""\/Date(975711661000)\/"", + ""LastModified"": ""\/Date(975711661000)\/"" + } + }, + { + ""Key"": ""key2"", + ""Value"": { + ""HourlyWage"": 2.0, + ""Name"": null, + ""BirthDate"": ""\/Date(975711661000)\/"", + ""LastModified"": ""\/Date(975711661000)\/"" + } + } +]", json); + + List> result = JsonConvert.DeserializeObject>>(json); + Assert.AreEqual(2, result.Count); + Assert.AreEqual("key1", result[0].Key); + Assert.AreEqual(1, result[0].Value.HourlyWage); + Assert.AreEqual("key2", result[1].Key); + Assert.AreEqual(2, result[1].Value.HourlyWage); + } + + public class StringListAppenderConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteValue(value); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + List existingStrings = (List)existingValue; + List newStrings = new List(existingStrings); + + reader.Read(); + + while (reader.TokenType != JsonToken.EndArray) + { + string s = (string)reader.Value; + newStrings.Add(s); + + reader.Read(); + } + + return newStrings; + } + + public override bool CanConvert(Type objectType) + { + return (objectType == typeof(List)); + } + } + + [Test] + public void StringListAppenderConverterTest() + { + Movie p = new Movie(); + p.ReleaseCountries = new List { "Existing" }; + + JsonConvert.PopulateObject("{'ReleaseCountries':['Appended']}", p, new JsonSerializerSettings + { + Converters = new List { new StringListAppenderConverter() } + }); + + Assert.AreEqual(2, p.ReleaseCountries.Count); + Assert.AreEqual("Existing", p.ReleaseCountries[0]); + Assert.AreEqual("Appended", p.ReleaseCountries[1]); + } + + public class StringAppenderConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteValue(value); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + string existingString = (string)existingValue; + string newString = existingString + (string)reader.Value; + + return newString; + } + + public override bool CanConvert(Type objectType) + { + return (objectType == typeof(string)); + } + } + + [Test] + public void StringAppenderConverterTest() + { + Movie p = new Movie(); + p.Name = "Existing,"; + + JsonConvert.PopulateObject("{'Name':'Appended'}", p, new JsonSerializerSettings + { + Converters = new List { new StringAppenderConverter() } + }); + + Assert.AreEqual(p.Name, "Existing,Appended"); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Additional content found in JSON reference object. A JSON reference object should only have a $ref property.")] + public void SerializeRefAdditionalContent() + { + //Additional text found in JSON string after finishing deserializing object. + //Test 1 + var reference = new Dictionary(); + reference.Add("$ref", "Persons"); + reference.Add("$id", 1); + + var child = new Dictionary(); + child.Add("_id", 2); + child.Add("Name", "Isabell"); + child.Add("Father", reference); + + var json = JsonConvert.SerializeObject(child); + JsonConvert.DeserializeObject>(json); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "JSON reference $ref property must have a string value.")] + public void SerializeRefBadType() + { + //Additional text found in JSON string after finishing deserializing object. + //Test 1 + var reference = new Dictionary(); + reference.Add("$ref", 1); + reference.Add("$id", 1); + + var child = new Dictionary(); + child.Add("_id", 2); + child.Add("Name", "Isabell"); + child.Add("Father", reference); + + var json = JsonConvert.SerializeObject(child); + JsonConvert.DeserializeObject>(json); + } + + public class ConstructorCompexIgnoredProperty + { + [JsonIgnore] + public Product Ignored { get; set; } + public string First { get; set; } + public int Second { get; set; } + + public ConstructorCompexIgnoredProperty(string first, int second) + { + First = first; + Second = second; + } + } + + [Test] + public void DeserializeIgnoredPropertyInConstructor() + { + string json = @"{""First"":""First"",""Second"":2,""Ignored"":{""Name"":""James""},""AdditionalContent"":{""LOL"":true}}"; + + ConstructorCompexIgnoredProperty cc = JsonConvert.DeserializeObject(json); + Assert.AreEqual("First", cc.First); + Assert.AreEqual(2, cc.Second); + Assert.AreEqual(null, cc.Ignored); + } + + public class ShouldSerializeTestClass + { + internal bool _shouldSerializeName; + + public string Name { get; set; } + public int Age { get; set; } + + public void ShouldSerializeAge() + { + // dummy. should never be used because it doesn't return bool + } + + public bool ShouldSerializeName() + { + return _shouldSerializeName; + } + } + + [Test] + public void ShouldSerializeTest() + { + ShouldSerializeTestClass c = new ShouldSerializeTestClass(); + c.Name = "James"; + c.Age = 27; + + string json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Age"": 27 +}", json); + + c._shouldSerializeName = true; + json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Name"": ""James"", + ""Age"": 27 +}", json); + + ShouldSerializeTestClass deserialized = JsonConvert.DeserializeObject(json); + Assert.AreEqual("James", deserialized.Name); + Assert.AreEqual(27, deserialized.Age); + } + + public class Employee + { + public string Name { get; set; } + public Employee Manager { get; set; } + + public bool ShouldSerializeManager() + { + return (Manager != this); + } + } + + [Test] + public void ShouldSerializeExample() + { + Employee joe = new Employee(); + joe.Name = "Joe Employee"; + Employee mike = new Employee(); + mike.Name = "Mike Manager"; + + joe.Manager = mike; + mike.Manager = mike; + + string json = JsonConvert.SerializeObject(new[] { joe, mike }, Formatting.Indented); + // [ + // { + // "Name": "Joe Employee", + // "Manager": { + // "Name": "Mike Manager" + // } + // }, + // { + // "Name": "Mike Manager" + // } + // ] + + Console.WriteLine(json); + } + + public class SpecifiedTestClass + { + private bool _nameSpecified; + + public string Name { get; set; } + public int Age { get; set; } + public int Weight { get; set; } + public int Height { get; set; } + + // dummy. should never be used because it isn't of type bool + [JsonIgnore] + public long AgeSpecified { get; set; } + + [JsonIgnore] + public bool NameSpecified + { + get { return _nameSpecified; } + set { _nameSpecified = value; } + } + + [JsonIgnore] + public bool WeightSpecified; + + [JsonIgnore] + [System.Xml.Serialization.XmlIgnoreAttribute] + public bool HeightSpecified; + } + + [Test] + public void SpecifiedTest() + { + SpecifiedTestClass c = new SpecifiedTestClass(); + c.Name = "James"; + c.Age = 27; + c.NameSpecified = false; + + string json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Age"": 27 +}", json); + + SpecifiedTestClass deserialized = JsonConvert.DeserializeObject(json); + Assert.IsNull(deserialized.Name); + Assert.IsFalse(deserialized.NameSpecified); + Assert.IsFalse(deserialized.WeightSpecified); + Assert.IsFalse(deserialized.HeightSpecified); + Assert.AreEqual(27, deserialized.Age); + + c.NameSpecified = true; + c.WeightSpecified = true; + c.HeightSpecified = true; + json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Name"": ""James"", + ""Age"": 27, + ""Weight"": 0, + ""Height"": 0 +}", json); + + deserialized = JsonConvert.DeserializeObject(json); + Assert.AreEqual("James", deserialized.Name); + Assert.IsTrue(deserialized.NameSpecified); + Assert.IsTrue(deserialized.WeightSpecified); + Assert.IsTrue(deserialized.HeightSpecified); + Assert.AreEqual(27, deserialized.Age); + } + + // [Test] + // public void XmlSerializerSpecifiedTrueTest() + // { + // XmlSerializer s = new XmlSerializer(typeof(OptionalOrder)); + + // StringWriter sw = new StringWriter(); + // s.Serialize(sw, new OptionalOrder() { FirstOrder = "First", FirstOrderSpecified = true }); + + // Console.WriteLine(sw.ToString()); + + // string xml = @" + // + // First + //"; + + // OptionalOrder o = (OptionalOrder)s.Deserialize(new StringReader(xml)); + // Console.WriteLine(o.FirstOrder); + // Console.WriteLine(o.FirstOrderSpecified); + // } + + // [Test] + // public void XmlSerializerSpecifiedFalseTest() + // { + // XmlSerializer s = new XmlSerializer(typeof(OptionalOrder)); + + // StringWriter sw = new StringWriter(); + // s.Serialize(sw, new OptionalOrder() { FirstOrder = "First", FirstOrderSpecified = false }); + + // Console.WriteLine(sw.ToString()); + + // // string xml = @" + // // + // // First + // //"; + + // // OptionalOrder o = (OptionalOrder)s.Deserialize(new StringReader(xml)); + // // Console.WriteLine(o.FirstOrder); + // // Console.WriteLine(o.FirstOrderSpecified); + // } + + public class OptionalOrder + { + // This field shouldn't be serialized + // if it is uninitialized. + public string FirstOrder; + // Use the XmlIgnoreAttribute to ignore the + // special field named "FirstOrderSpecified". + [System.Xml.Serialization.XmlIgnoreAttribute] + public bool FirstOrderSpecified; + } + + public class FamilyDetails + { + public string Name { get; set; } + public int NumberOfChildren { get; set; } + + [JsonIgnore] + public bool NumberOfChildrenSpecified { get; set; } + } + + [Test] + public void SpecifiedExample() + { + FamilyDetails joe = new FamilyDetails(); + joe.Name = "Joe Family Details"; + joe.NumberOfChildren = 4; + joe.NumberOfChildrenSpecified = true; + + FamilyDetails martha = new FamilyDetails(); + martha.Name = "Martha Family Details"; + martha.NumberOfChildren = 3; + martha.NumberOfChildrenSpecified = false; + + string json = JsonConvert.SerializeObject(new[] { joe, martha }, Formatting.Indented); + //[ + // { + // "Name": "Joe Family Details", + // "NumberOfChildren": 4 + // }, + // { + // "Name": "Martha Family Details" + // } + //] + Console.WriteLine(json); + + string mikeString = "{\"Name\": \"Mike Person\"}"; + FamilyDetails mike = JsonConvert.DeserializeObject(mikeString); + + Console.WriteLine("mikeString specifies number of children: {0}", mike.NumberOfChildrenSpecified); + + string mikeFullDisclosureString = "{\"Name\": \"Mike Person\", \"NumberOfChildren\": \"0\"}"; + mike = JsonConvert.DeserializeObject(mikeFullDisclosureString); + + Console.WriteLine("mikeString specifies number of children: {0}", mike.NumberOfChildrenSpecified); + } + + public class DictionaryKey + { + public string Value { get; set; } + + public override string ToString() + { + return Value; + } + + public static implicit operator DictionaryKey(string value) + { + return new DictionaryKey() { Value = value }; + } + } + + [Test] + public void SerializeDeserializeDictionaryKey() + { + Dictionary dictionary = new Dictionary(); + + dictionary.Add(new DictionaryKey() { Value = "First!" }, "First"); + dictionary.Add(new DictionaryKey() { Value = "Second!" }, "Second"); + + string json = JsonConvert.SerializeObject(dictionary, Formatting.Indented); + + Assert.AreEqual(@"{ + ""First!"": ""First"", + ""Second!"": ""Second"" +}", json); + + Dictionary newDictionary = + JsonConvert.DeserializeObject>(json); + + Assert.AreEqual(2, newDictionary.Count); + } + + [Test] + public void SerializeNullableArray() + { + string jsonText = JsonConvert.SerializeObject(new double?[] { 2.4, 4.3, null }, Formatting.Indented); + + Assert.AreEqual(@"[ + 2.4, + 4.3, + null +]", jsonText); + + double?[] d = (double?[])JsonConvert.DeserializeObject(jsonText, typeof(double?[])); + + Assert.AreEqual(3, d.Length); + Assert.AreEqual(2.4, d[0]); + Assert.AreEqual(4.3, d[1]); + Assert.AreEqual(null, d[2]); + } + +#if !SILVERLIGHT && !NET20 && !PocketPC + [Test] + public void SerializeHashSet() + { + string jsonText = JsonConvert.SerializeObject(new HashSet() + { + "One", + "2", + "III" + }, Formatting.Indented); + + Assert.AreEqual(@"[ + ""One"", + ""2"", + ""III"" +]", jsonText); + + HashSet d = JsonConvert.DeserializeObject>(jsonText); + + Assert.AreEqual(3, d.Count); + Assert.IsTrue(d.Contains("One")); + Assert.IsTrue(d.Contains("2")); + Assert.IsTrue(d.Contains("III")); + } +#endif + + private class MyClass + { + public byte[] Prop1 { get; set; } + + public MyClass() + { + Prop1 = new byte[0]; + } + } + + [Test] + public void DeserializeByteArray() + { + JsonSerializer serializer1 = new JsonSerializer(); + serializer1.Converters.Add(new IsoDateTimeConverter()); + serializer1.NullValueHandling = NullValueHandling.Ignore; + + string json = @"[{""Prop1"":""""},{""Prop1"":""""}]"; + + JsonTextReader reader = new JsonTextReader(new StringReader(json)); + + MyClass[] z = (MyClass[])serializer1.Deserialize(reader, typeof(MyClass[])); + Assert.AreEqual(2, z.Length); + Assert.AreEqual(0, z[0].Prop1.Length); + Assert.AreEqual(0, z[1].Prop1.Length); + } + +#if !NET20 && !PocketPC && !SILVERLIGHT + public class StringDictionaryTestClass + { + public StringDictionary StringDictionaryProperty { get; set; } + } + + [Test] + [ExpectedException(typeof(Exception), ExpectedMessage = "Cannot create and populate list type System.Collections.Specialized.StringDictionary.")] + public void StringDictionaryTest() + { + StringDictionaryTestClass s1 = new StringDictionaryTestClass() + { + StringDictionaryProperty = new StringDictionary() + { + {"1", "One"}, + {"2", "II"}, + {"3", "3"} + } + }; + + string json = JsonConvert.SerializeObject(s1, Formatting.Indented); + + JsonConvert.DeserializeObject(json); + } +#endif + + [JsonObject(MemberSerialization.OptIn)] + public struct StructWithAttribute + { + public string MyString { get; set; } + [JsonProperty] + public int MyInt { get; set; } + } + + [Test] + public void SerializeStructWithJsonObjectAttribute() + { + StructWithAttribute testStruct = new StructWithAttribute + { + MyInt = int.MaxValue + }; + + string json = JsonConvert.SerializeObject(testStruct, Formatting.Indented); + + Assert.AreEqual(@"{ + ""MyInt"": 2147483647 +}", json); + + StructWithAttribute newStruct = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(int.MaxValue, newStruct.MyInt); + } + + public class TimeZoneOffsetObject + { + public DateTimeOffset Offset { get; set; } + } + +#if !NET20 + [Test] + public void ReadWriteTimeZoneOffset() + { + var serializeObject = JsonConvert.SerializeObject(new TimeZoneOffsetObject + { + Offset = new DateTimeOffset(new DateTime(2000, 1, 1), TimeSpan.FromHours(6)) + }); + + Assert.AreEqual("{\"Offset\":\"\\/Date(946663200000+0600)\\/\"}", serializeObject); + var deserializeObject = JsonConvert.DeserializeObject(serializeObject); + Assert.AreEqual(TimeSpan.FromHours(6), deserializeObject.Offset.Offset); + Assert.AreEqual(new DateTime(2000, 1, 1), deserializeObject.Offset.Date); + } + + [Test] + public void DeserializePropertyNullableDateTimeOffsetExact() + { + NullableDateTimeTestClass d = JsonConvert.DeserializeObject("{\"DateTimeOffsetField\":\"\\/Date(946663200000+0600)\\/\"}"); + Assert.AreEqual(new DateTimeOffset(new DateTime(2000, 1, 1), TimeSpan.FromHours(6)), d.DateTimeOffsetField); + } +#endif + + public abstract class LogEvent + { + [JsonProperty("event")] + public abstract string EventName { get; } + } + + public class DerivedEvent : LogEvent + { + public override string EventName { get { return "derived"; } } + } + + [Test] + public void OverridenPropertyMembers() + { + string json = JsonConvert.SerializeObject(new DerivedEvent(), Formatting.Indented); + + Assert.AreEqual(@"{ + ""event"": ""derived"" +}", json); + } + +#if !(NET35 || NET20 || WINDOWS_PHONE) + [Test] + public void SerializeExpandoObject() + { + dynamic expando = new ExpandoObject(); + expando.Int = 1; + expando.Decimal = 99.9d; + expando.Complex = new ExpandoObject(); + expando.Complex.String = "I am a string"; + expando.Complex.DateTime = new DateTime(2000, 12, 20, 18, 55, 0, DateTimeKind.Utc); + + string json = JsonConvert.SerializeObject(expando, Formatting.Indented); + Assert.AreEqual(@"{ + ""Int"": 1, + ""Decimal"": 99.9, + ""Complex"": { + ""String"": ""I am a string"", + ""DateTime"": ""\/Date(977338500000)\/"" + } +}", json); + + IDictionary newExpando = JsonConvert.DeserializeObject(json); + + Assert.IsInstanceOfType(typeof(long), newExpando["Int"]); + Assert.AreEqual(expando.Int, newExpando["Int"]); + + Assert.IsInstanceOfType(typeof(double), newExpando["Decimal"]); + Assert.AreEqual(expando.Decimal, newExpando["Decimal"]); + + Assert.IsInstanceOfType(typeof(ExpandoObject), newExpando["Complex"]); + IDictionary o = (ExpandoObject)newExpando["Complex"]; + + Assert.IsInstanceOfType(typeof(string), o["String"]); + Assert.AreEqual(expando.Complex.String, o["String"]); + + Assert.IsInstanceOfType(typeof(DateTime), o["DateTime"]); + Assert.AreEqual(expando.Complex.DateTime, o["DateTime"]); + } +#endif + + [Test] + public void DeserializeDecimalExact() + { + decimal d = JsonConvert.DeserializeObject("123456789876543.21"); + Assert.AreEqual(123456789876543.21m, d); + } + + [Test] + public void DeserializeNullableDecimalExact() + { + decimal? d = JsonConvert.DeserializeObject("123456789876543.21"); + Assert.AreEqual(123456789876543.21m, d); + } + + [Test] + public void DeserializeDecimalPropertyExact() + { + string json = "{Amount:123456789876543.21}"; + Invoice i = JsonConvert.DeserializeObject(json); + Assert.AreEqual(123456789876543.21m, i.Amount); + } + + [Test] + public void DeserializeDecimalArrayExact() + { + string json = "[123456789876543.21]"; + IList a = JsonConvert.DeserializeObject>(json); + Assert.AreEqual(123456789876543.21m, a[0]); + } + + [Test] + public void DeserializeDecimalDictionaryExact() + { + string json = "{'Value':123456789876543.21}"; + IDictionary d = JsonConvert.DeserializeObject>(json); + Assert.AreEqual(123456789876543.21m, d["Value"]); + } + + public struct Vector + { + public float X; + public float Y; + public float Z; + + public override string ToString() + { + return string.Format("({0},{1},{2})", X, Y, Z); + } + } + + public class VectorParent + { + public Vector Position; + } + + [Test] + public void DeserializeStructProperty() + { + VectorParent obj = new VectorParent(); + obj.Position = new Vector { X = 1, Y = 2, Z = 3 }; + + string str = JsonConvert.SerializeObject(obj); + + obj = JsonConvert.DeserializeObject(str); + + Assert.AreEqual(1, obj.Position.X); + Assert.AreEqual(2, obj.Position.Y); + Assert.AreEqual(3, obj.Position.Z); + } + + [JsonObject(MemberSerialization.OptIn)] + public class Derived : Base + { + [JsonProperty] + public string IDoWork { get; private set; } + + private Derived() { } + + internal Derived(string dontWork, string doWork) + : base(dontWork) + { + IDoWork = doWork; + } + } + + [JsonObject(MemberSerialization.OptIn)] + public class Base + { + [JsonProperty] + public string IDontWork { get; private set; } + + protected Base() { } + + internal Base(string dontWork) + { + IDontWork = dontWork; + } + } + + [Test] + public void PrivateSetterOnBaseClassProperty() + { + var derived = new Derived("meh", "woo"); + + var settings = new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects, + ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor + }; + + string json = JsonConvert.SerializeObject(derived, Formatting.Indented, settings); + + var meh = JsonConvert.DeserializeObject(json, settings); + + Assert.AreEqual(((Derived)meh).IDoWork, "woo"); + Assert.AreEqual(meh.IDontWork, "meh"); + } + +#if !(SILVERLIGHT || PocketPC || NET20) + [DataContract] + public struct StructISerializable : ISerializable + { + private string _name; + + public StructISerializable(SerializationInfo info, StreamingContext context) + { + _name = info.GetString("Name"); + } + + [DataMember] + public string Name + { + get { return _name; } + set { _name = value; } + } + + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("Name", _name); + } + } + + [DataContract] + public class NullableStructPropertyClass + { + private StructISerializable _foo1; + private StructISerializable? _foo2; + + [DataMember] + public StructISerializable Foo1 + { + get { return _foo1; } + set { _foo1 = value; } + } + + [DataMember] + public StructISerializable? Foo2 + { + get { return _foo2; } + set { _foo2 = value; } + } + } + + [Test] + public void DeserializeNullableStruct() + { + NullableStructPropertyClass nullableStructPropertyClass = new NullableStructPropertyClass(); + nullableStructPropertyClass.Foo1 = new StructISerializable() { Name = "foo 1" }; + nullableStructPropertyClass.Foo2 = new StructISerializable() { Name = "foo 2" }; + + NullableStructPropertyClass barWithNull = new NullableStructPropertyClass(); + barWithNull.Foo1 = new StructISerializable() { Name = "foo 1" }; + barWithNull.Foo2 = null; + + //throws error on deserialization because bar1.Foo2 is of type Foo? + string s = JsonConvert.SerializeObject(nullableStructPropertyClass); + NullableStructPropertyClass deserialized = deserialize(s); + Assert.AreEqual(deserialized.Foo1.Name, "foo 1"); + Assert.AreEqual(deserialized.Foo2.Value.Name, "foo 2"); + + //no error Foo2 is null + s = JsonConvert.SerializeObject(barWithNull); + deserialized = deserialize(s); + Assert.AreEqual(deserialized.Foo1.Name, "foo 1"); + Assert.AreEqual(deserialized.Foo2, null); + } + + + static NullableStructPropertyClass deserialize(string serStr) + { + return JsonConvert.DeserializeObject( + serStr, + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore + }); + } +#endif + + public class Response + { + public string Name { get; set; } + public JToken Data { get; set; } + } + + [Test] + public void DeserializeJToken() + { + Response response = new Response + { + Name = "Success", + Data = new JObject(new JProperty("First", "Value1"), new JProperty("Second", "Value2")) + }; + + string json = JsonConvert.SerializeObject(response, Formatting.Indented); + + Response deserializedResponse = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("Success", deserializedResponse.Name); + Assert.IsTrue(deserializedResponse.Data.DeepEquals(response.Data)); + } + + public abstract class Test + { + public abstract T Value { get; set; } + } + + [JsonObject(MemberSerialization.OptIn)] + public class DecimalTest : Test + { + protected DecimalTest() { } + public DecimalTest(decimal val) + { + Value = val; + } + + [JsonProperty] + public override decimal Value { get; set; } + } + + [Test] + public void OnError() + { + var data = new DecimalTest(decimal.MinValue); + var json = JsonConvert.SerializeObject(data); + var obj = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(decimal.MinValue, obj.Value); + } + + public class NonPublicConstructorWithJsonConstructor + { + public string Value { get; private set; } + public string Constructor { get; private set; } + + [JsonConstructor] + private NonPublicConstructorWithJsonConstructor() + { + Constructor = "NonPublic"; + } + + public NonPublicConstructorWithJsonConstructor(string value) + { + Value = value; + Constructor = "Public Paramatized"; + } + } + + [Test] + public void NonPublicConstructorWithJsonConstructorTest() + { + NonPublicConstructorWithJsonConstructor c = JsonConvert.DeserializeObject("{}"); + Assert.AreEqual("NonPublic", c.Constructor); + } + + public class PublicConstructorOverridenByJsonConstructor + { + public string Value { get; private set; } + public string Constructor { get; private set; } + + public PublicConstructorOverridenByJsonConstructor() + { + Constructor = "NonPublic"; + } + + [JsonConstructor] + public PublicConstructorOverridenByJsonConstructor(string value) + { + Value = value; + Constructor = "Public Paramatized"; + } + } + + [Test] + public void PublicConstructorOverridenByJsonConstructorTest() + { + PublicConstructorOverridenByJsonConstructor c = JsonConvert.DeserializeObject("{Value:'value!'}"); + Assert.AreEqual("Public Paramatized", c.Constructor); + Assert.AreEqual("value!", c.Value); + } + + public class MultipleParamatrizedConstructorsJsonConstructor + { + public string Value { get; private set; } + public int Age { get; private set; } + public string Constructor { get; private set; } + + public MultipleParamatrizedConstructorsJsonConstructor(string value) + { + Value = value; + Constructor = "Public Paramatized 1"; + } + + [JsonConstructor] + public MultipleParamatrizedConstructorsJsonConstructor(string value, int age) + { + Value = value; + Age = age; + Constructor = "Public Paramatized 2"; + } + } + + [Test] + public void MultipleParamatrizedConstructorsJsonConstructorTest() + { + MultipleParamatrizedConstructorsJsonConstructor c = JsonConvert.DeserializeObject("{Value:'value!', Age:1}"); + Assert.AreEqual("Public Paramatized 2", c.Constructor); + Assert.AreEqual("value!", c.Value); + Assert.AreEqual(1, c.Age); + } + + public class EnumerableClass + { + public IEnumerable Enumerable { get; set; } + } + + [Test] + public void DeserializeEnumerable() + { + EnumerableClass c = new EnumerableClass + { + Enumerable = new List { "One", "Two", "Three" } + }; + + string json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Enumerable"": [ + ""One"", + ""Two"", + ""Three"" + ] +}", json); + + EnumerableClass c2 = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("One", c2.Enumerable.ElementAt(0)); + Assert.AreEqual("Two", c2.Enumerable.ElementAt(1)); + Assert.AreEqual("Three", c2.Enumerable.ElementAt(2)); + } + + [JsonObject(MemberSerialization.OptIn)] + public class ItemBase + { + [JsonProperty] + public string Name { get; set; } + } + + public class ComplexItem : ItemBase + { + public Stream Source { get; set; } + } + + [Test] + public void SerializeAttributesOnBase() + { + ComplexItem i = new ComplexItem(); + + string json = JsonConvert.SerializeObject(i, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Name"": null +}", json); + } + + public class DeserializeStringConvert + { + public string Name { get; set; } + public int Age { get; set; } + public double Height { get; set; } + public decimal Price { get; set; } + } + + [Test] + public void DeserializeStringEnglish() + { + string json = @"{ + 'Name': 'James Hughes', + 'Age': '40', + 'Height': '44.4', + 'Price': '4' +}"; + + DeserializeStringConvert p = JsonConvert.DeserializeObject(json); + Assert.AreEqual(40, p.Age); + Assert.AreEqual(44.4, p.Height); + Assert.AreEqual(4d, p.Price); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Error converting value {null} to type 'System.DateTime'.")] + public void DeserializeNullDateTimeValueTest() + { + JsonConvert.DeserializeObject("null", typeof(DateTime)); + } + + [Test] + public void DeserializeNullNullableDateTimeValueTest() + { + object dateTime = JsonConvert.DeserializeObject("null", typeof(DateTime?)); + + Assert.IsNull(dateTime); + } + + [Test] + public void MultiIndexSuperTest() + { + MultiIndexSuper e = new MultiIndexSuper(); + + string json = JsonConvert.SerializeObject(e, Formatting.Indented); + + Assert.AreEqual(@"{}", json); + } + + public class MultiIndexSuper : MultiIndexBase + { + + } + + public abstract class MultiIndexBase + { + protected internal object this[string propertyName] + { + get { return null; } + set { } + } + protected internal object this[object property] + { + get { return null; } + set { } + } + } + + public class CommentTestClass + { + public bool Indexed { get; set; } + public int StartYear { get; set; } + public IList Values { get; set; } + } + + [Test] + public void CommentTestClassTest() + { + string json = @"{""indexed"":true, ""startYear"":1939, ""values"": + [ 3000, /* 1940-1949 */ + 3000, 3600, 3600, 3600, 3600, 4200, 4200, 4200, 4200, 4800, /* 1950-1959 */ + 4800, 4800, 4800, 4800, 4800, 4800, 6600, 6600, 7800, 7800, /* 1960-1969 */ + 7800, 7800, 9000, 10800, 13200, 14100, 15300, 16500, 17700, 22900, /* 1970-1979 */ + 25900, 29700, 32400, 35700, 37800, 39600, 42000, 43800, 45000, 48000, /* 1980-1989 */ + 51300, 53400, 55500, 57600, 60600, 61200, 62700, 65400, 68400, 72600, /* 1990-1999 */ + 76200, 80400, 84900, 87000, 87900, 90000, 94200, 97500, 102000, 106800, /* 2000-2009 */ + 106800, 106800] /* 2010-2011 */ + }"; + + CommentTestClass commentTestClass = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(true, commentTestClass.Indexed); + Assert.AreEqual(1939, commentTestClass.StartYear); + Assert.AreEqual(63, commentTestClass.Values.Count); + } + + class DTOWithParameterisedConstructor + { + public DTOWithParameterisedConstructor(string A) + { + this.A = A; + B = 2; + } + + public string A { get; set; } + public int? B { get; set; } + } + + class DTOWithoutParameterisedConstructor + { + public DTOWithoutParameterisedConstructor() + { + B = 2; + } + + public string A { get; set; } + public int? B { get; set; } + } + + [Test] + public void PopulationBehaviourForOmittedPropertiesIsTheSameForParameterisedConstructorAsForDefaultConstructor() + { + string json = @"{A:""Test""}"; + + var withoutParameterisedConstructor = JsonConvert.DeserializeObject(json); + var withParameterisedConstructor = JsonConvert.DeserializeObject(json); + Assert.AreEqual(withoutParameterisedConstructor.B, withParameterisedConstructor.B); + } + } +} \ No newline at end of file