--- /dev/null
+#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<string, object> testDictionary = new Dictionary<string, object>();
+ testDictionary["date"] = dateValue;
+
+ string jsonText = JsonConvert.SerializeObject(testDictionary);
+
+#if !PocketPC && !NET20 && !WINDOWS_PHONE
+ MemoryStream ms = new MemoryStream();
+ DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Dictionary<string, object>));
+ serializer.WriteObject(ms, testDictionary);
+
+ byte[] data = ms.ToArray();
+ string output = Encoding.UTF8.GetString(data, 0, data.Length);
+#endif
+
+ Dictionary<string, object> deserializedDictionary = (Dictionary<string, object>)JsonConvert.DeserializeObject(jsonText, typeof(Dictionary<string, object>));
+ 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<GetOnlyPropertyClass>(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<SetOnlyPropertyClass>(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<JsonIgnoreAttributeTestClass>(@"{""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<JsonPropertyClass>(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<ArticleCollection>(jsonText);
+
+ Assert.AreEqual(articles1.Count, articles2.Count);
+ Assert.AreEqual(articles1[0].Name, articles2[0].Name);
+ }
+
+ [Test]
+ public void ReadOnlyCollectionSerialize()
+ {
+ ReadOnlyCollection<int> r1 = new ReadOnlyCollection<int>(new int[] { 0, 1, 2, 3, 4 });
+
+ string jsonText = JsonConvert.SerializeObject(r1);
+
+ ReadOnlyCollection<int> r2 = JsonConvert.DeserializeObject<ReadOnlyCollection<int>>(jsonText);
+
+ CollectionAssert.AreEqual(r1, r2);
+ }
+
+#if !PocketPC && !NET20 && !WINDOWS_PHONE
+ [Test]
+ public void Unicode()
+ {
+ string json = @"[""PRE\u003cPOST""]";
+
+ DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List<string>));
+ List<string> dataContractResult = (List<string>)s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
+
+ List<string> jsonNetResult = JsonConvert.DeserializeObject<List<string>>(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<string> javaScriptSerializerResult = javaScriptSerializer.Deserialize<List<string>>(json);
+#endif
+
+ DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List<string>));
+ List<string> dataContractResult = (List<string>)s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
+
+ List<string> jsonNetResult = JsonConvert.DeserializeObject<List<string>>(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<List<string>>(json);
+ }
+
+ [Test]
+ public void DateTimeTest()
+ {
+ List<DateTime> testDates = new List<DateTime> {
+ new DateTime(100, 1, 1, 1, 1, 1, DateTimeKind.Local),
+ new DateTime(100, 1, 1, 1, 1, 1, DateTimeKind.Unspecified),
+ new DateTime(100, 1, 1, 1, 1, 1, DateTimeKind.Utc),
+ new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Local),
+ new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Unspecified),
+ new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc),
+ };
+ string result;
+
+
+ MemoryStream ms = new MemoryStream();
+ DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List<DateTime>));
+ s.WriteObject(ms, testDates);
+ ms.Seek(0, SeekOrigin.Begin);
+ StreamReader sr = new StreamReader(ms);
+
+ string expected = sr.ReadToEnd();
+
+ result = JsonConvert.SerializeObject(testDates);
+ Assert.AreEqual(expected, result);
+ }
+
+ [Test]
+ public void DateTimeOffset()
+ {
+ List<DateTimeOffset> testDates = new List<DateTimeOffset> {
+ new DateTimeOffset(new DateTime(100, 1, 1, 1, 1, 1, DateTimeKind.Utc)),
+ new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.Zero),
+ new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.FromHours(13)),
+ new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.FromHours(-3.5)),
+ };
+
+ string result = JsonConvert.SerializeObject(testDates);
+ Assert.AreEqual(@"[""\/Date(-59011455539000+0000)\/"",""\/Date(946688461000+0000)\/"",""\/Date(946641661000+1300)\/"",""\/Date(946701061000-0330)\/""]", result);
+ }
+#endif
+
+ [Test]
+ public void NonStringKeyDictionary()
+ {
+ Dictionary<int, int> values = new Dictionary<int, int>();
+ values.Add(-5, 6);
+ values.Add(int.MinValue, int.MaxValue);
+
+ string json = JsonConvert.SerializeObject(values);
+
+ Assert.AreEqual(@"{""-5"":6,""-2147483648"":2147483647}", json);
+
+ Dictionary<int, int> newValues = JsonConvert.DeserializeObject<Dictionary<int, int>>(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<ClassWithArray>(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<ClassWithArray>(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<ClassWithArray>(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<ConverableMembers>(json);
+ Assert.AreEqual("string", c.String);
+ Assert.AreEqual(double.MaxValue, c.Double);
+ Assert.AreEqual(DBNull.Value, c.DBNull);
+ }
+
+ [Test]
+ public void SerializeStack()
+ {
+ Stack<object> s = new Stack<object>();
+ 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<ClassWithGuid>(json);
+ Assert.AreEqual(guid, c.GuidField);
+ }
+
+ [Test]
+ public void EnumTest()
+ {
+ string json = JsonConvert.SerializeObject(StringComparison.CurrentCultureIgnoreCase);
+ Assert.AreEqual(@"1", json);
+
+ StringComparison s = JsonConvert.DeserializeObject<StringComparison>(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<ClassWithTimeSpan>(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<JsonIgnoreAttributeOnClassTestClass>(@"{""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<ArrayList>(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<Name>(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<ConstructorCaseSensitivityClass>(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<ConverterPrecedenceClass>(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<ConverterPrecedenceClass>(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<MemberConverterClass>(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<MemberConverterClass>(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<ClassAndMemberConverterClass>(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<PersonRaw>(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<UserNullable>(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<DoubleClass>(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<TypeClass>(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<TypeClass>(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<RequiredMembersClass>(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<RequiredMembersClass>(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<RequiredMembersClass>(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<RequiredMembersClass>(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<JaggedArray>(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<GoogleMapGeocoderStructure>(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<string, int>
+ {
+ {"one", 1},
+ {"two", 2},
+ {"three", 3}
+ };
+ o.IListProperty = new List<int>
+ {
+ 1, 2, 3
+ };
+ o.IEnumerableProperty = new List<int>
+ {
+ 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<GenericListAndDictionaryInterfaceProperties>(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<PropertyCase>(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<SubKlass>(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<RequestOnly>(json);
+ Assert.AreEqual("ux.settings.update", r.Request);
+
+ NonRequest n = JsonConvert.DeserializeObject<NonRequest>(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<OptInClass>(@"{
+ ""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<DataContractPrivateMembers>(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<DictionaryInterfaceClass>(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<DictionaryInterfaceClass>(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<Shortie>(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<Uri>(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<Content>
+ {
+ 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<Content>(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<RoleTransfer>(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<ObjectArrayPropertyTest>(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<ObjectArrayPropertyTest>(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<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(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<Product> products = new List<Product>();
+ 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<Product> products = JsonConvert.DeserializeObject<List<Product>>(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<NullableDateTimeTestClass>(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<Event>(json);
+ }
+
+ [Test]
+ public void DeserializeObjectSetOnlyProperty()
+ {
+ string json = @"{'SetOnlyProperty':[1,2,3,4,5]}";
+
+ SetOnlyPropertyClass2 setOnly = JsonConvert.DeserializeObject<SetOnlyPropertyClass2>(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<ListTestClass>(json);
+ }
+
+ [Test]
+ public void DeserializeNullableListWithNulls()
+ {
+ List<decimal?> l = JsonConvert.DeserializeObject<List<decimal?>>("[ 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<Person>(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<List<Person>>(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<Person>());
+ }
+
+ [Test]
+ public void DeserializeEmptyString()
+ {
+ string json = @"{""Name"":""""}";
+
+ Person p = JsonConvert.DeserializeObject<Person>(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<MemoryStream>("{ReadTimeout:0}");
+ }
+
+ [Test]
+ [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error converting value """" to type 'System.Int32'.")]
+ public void DeserializeEnsureTypeEmptyStringToIntError()
+ {
+ JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:''}");
+ }
+
+ [Test]
+ [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error converting value {null} to type 'System.Int32'.")]
+ public void DeserializeEnsureTypeNullToIntError()
+ {
+ JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:null}");
+ }
+
+ [Test]
+ public void SerializeGenericListOfStrings()
+ {
+ List<String> strings = new List<String>();
+
+ 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<ConstructorReadonlyFields>(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<StructTest>(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<Foo>(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<Guid, int> dictionary = new Dictionary<Guid, int>();
+ 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<Person, int> dictionary = new Dictionary<Person, int>();
+ 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<Dictionary<Person, int>>(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"": ""<b>Paris Hilton</b> - 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"": ""<b>Paris Hilton</b>"",
+ ""titleNoFormatting"": ""Paris Hilton"",
+ ""content"": ""Self: Zoolander. Socialite <b>Paris Hilton</b>...""
+ }
+ ],
+ ""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<JToken> results = googleSearch["responseData"]["results"].Children().ToList();
+
+ // serialize JSON results into .NET objects
+ IList<SearchResult> searchResults = new List<SearchResult>();
+ foreach (JToken result in results)
+ {
+ SearchResult searchResult = JsonConvert.DeserializeObject<SearchResult>(result.ToString());
+ searchResults.Add(searchResult);
+ }
+
+ // Title = <b>Paris Hilton</b> - Wikipedia, the free encyclopedia
+ // Content = [1] In 2006, she released her debut album...
+ // Url = http://en.wikipedia.org/wiki/Paris_Hilton
+
+ // Title = <b>Paris Hilton</b>
+ // Content = Self: Zoolander. Socialite <b>Paris Hilton</b>...
+ // Url = http://www.imdb.com/name/nm0385296/
+
+ Assert.AreEqual(2, searchResults.Count);
+ Assert.AreEqual("<b>Paris Hilton</b> - Wikipedia, the free encyclopedia", searchResults[0].Title);
+ Assert.AreEqual("<b>Paris Hilton</b>", 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<PersonPropertyClass>(json);
+ Assert.AreEqual(wagePerson.HourlyWage, ((WagePerson)newPersonPropertyClass.Person).HourlyWage);
+ }
+
+ public class ExistingValueClass
+ {
+ public Dictionary<string, string> Dictionary { get; set; }
+ public List<string> List { get; set; }
+
+ public ExistingValueClass()
+ {
+ Dictionary = new Dictionary<string, string>
+ {
+ {"existing", "yup"}
+ };
+ List = new List<string>
+ {
+ "existing"
+ };
+ }
+ }
+
+ [Test]
+ public void DeserializePopulateDictionaryAndList()
+ {
+ ExistingValueClass d = JsonConvert.DeserializeObject<ExistingValueClass>(@"{'Dictionary':{appended:'appended',existing:'new'}}");
+
+ Assert.IsNotNull(d);
+ Assert.IsNotNull(d.Dictionary);
+ Assert.AreEqual(typeof(Dictionary<string, string>), d.Dictionary.GetType());
+ Assert.AreEqual(typeof(List<string>), 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<T> where T : IKeyValueId
+ {
+ private Dictionary<string, T> _dict1 = new Dictionary<string, T>();
+
+ 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<T>(); }
+ set
+ {
+ foreach (var item in value)
+ this.Add(item);
+ }
+ }
+ }
+
+ [Test]
+ public void IgnoreIndexedProperties()
+ {
+ ThisGenericTest<KeyValueId> g = new ThisGenericTest<KeyValueId>();
+
+ 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<KeyValueId> gen = JsonConvert.DeserializeObject<ThisGenericTest<KeyValueId>>(json);
+ Assert.AreEqual("some value", gen.MyProperty);
+ }
+
+ public class JRawValueTestObject
+ {
+ public JRaw Value { get; set; }
+ }
+
+ [Test]
+ public void JRawValue()
+ {
+ JRawValueTestObject deserialized = JsonConvert.DeserializeObject<JRawValueTestObject>("{value:3}");
+ Assert.AreEqual("3", deserialized.Value.ToString());
+
+ deserialized = JsonConvert.DeserializeObject<JRawValueTestObject>("{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<DictionaryWithNoDefaultConstructor>(json);
+ }
+
+ public class DictionaryWithNoDefaultConstructor : Dictionary<string, string>
+ {
+ public DictionaryWithNoDefaultConstructor(IEnumerable<KeyValuePair<string, string>> initial)
+ {
+ foreach (KeyValuePair<string, string> 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<TestClass>(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<T> : IDictionary<string, T>
+ {
+
+ private readonly Dictionary<string, T> _innerDictionary = new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
+
+ public ModelStateDictionary()
+ {
+ }
+
+ public ModelStateDictionary(ModelStateDictionary<T> 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<string, T>)_innerDictionary).IsReadOnly;
+ }
+ }
+
+ public ICollection<string> 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<T> Values
+ {
+ get
+ {
+ return _innerDictionary.Values;
+ }
+ }
+
+ public void Add(KeyValuePair<string, T> item)
+ {
+ ((IDictionary<string, T>)_innerDictionary).Add(item);
+ }
+
+ public void Add(string key, T value)
+ {
+ _innerDictionary.Add(key, value);
+ }
+
+ public void Clear()
+ {
+ _innerDictionary.Clear();
+ }
+
+ public bool Contains(KeyValuePair<string, T> item)
+ {
+ return ((IDictionary<string, T>)_innerDictionary).Contains(item);
+ }
+
+ public bool ContainsKey(string key)
+ {
+ return _innerDictionary.ContainsKey(key);
+ }
+
+ public void CopyTo(KeyValuePair<string, T>[] array, int arrayIndex)
+ {
+ ((IDictionary<string, T>)_innerDictionary).CopyTo(array, arrayIndex);
+ }
+
+ public IEnumerator<KeyValuePair<string, T>> GetEnumerator()
+ {
+ return _innerDictionary.GetEnumerator();
+ }
+
+ public void Merge(ModelStateDictionary<T> dictionary)
+ {
+ if (dictionary == null)
+ {
+ return;
+ }
+
+ foreach (var entry in dictionary)
+ {
+ this[entry.Key] = entry.Value;
+ }
+ }
+
+ public bool Remove(KeyValuePair<string, T> item)
+ {
+ return ((IDictionary<string, T>)_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<string> modelStateDictionary = new ModelStateDictionary<string>();
+ modelStateDictionary.Add("key", "value");
+
+ string json = JsonConvert.SerializeObject(modelStateDictionary);
+
+ Assert.AreEqual(@"{""key"":""value""}", json);
+
+ ModelStateDictionary<string> newModelStateDictionary = JsonConvert.DeserializeObject<ModelStateDictionary<string>>(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<ISerializableTestObject>(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<TKey, TValue>
+ {
+ 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<KVPair<string, string>> kvPairs =
+ JsonConvert.DeserializeObject<List<KVPair<string, string>>>(
+ "[{\"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>(
+ @"{
+ ""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>(
+ @"{
+ ""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("<root>hehe, root</root>");
+ testObject.Element = XElement.Parse(@"<fifth xmlns:json=""http://json.org"" json:Awesome=""true"">element</fifth>");
+
+ 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<XNodeTestObject>(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("<root>hehe, root</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<XmlNodeTestObject>(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<int, object> d1 = new Dictionary<int, object>();
+ d1.Add(5, s);
+ Assert.AreEqual(@"{""5"":""host\\user""}", JsonConvert.SerializeObject(d1));
+
+ Dictionary<string, object> d2 = new Dictionary<string, object>();
+ d2.Add(s, 5);
+ Assert.AreEqual(@"{""host\\user"":5}", JsonConvert.SerializeObject(d2));
+ }
+
+ public class GenericListTestClass
+ {
+ public List<string> GenericList { get; set; }
+
+ public GenericListTestClass()
+ {
+ GenericList = new List<string>();
+ }
+ }
+
+ [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<GenericListTestClass>(json);
+ Assert.AreEqual(2, newValue.GenericList.Count);
+ Assert.AreEqual(typeof(List<string>), newValue.GenericList.GetType());
+ }
+
+ [Test]
+ public void DeserializeSimpleKeyValuePair()
+ {
+ List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
+ list.Add(new KeyValuePair<string, string>("key1", "value1"));
+ list.Add(new KeyValuePair<string, string>("key2", "value2"));
+
+ string json = JsonConvert.SerializeObject(list);
+
+ Assert.AreEqual(@"[{""Key"":""key1"",""Value"":""value1""},{""Key"":""key2"",""Value"":""value2""}]", json);
+
+ List<KeyValuePair<string, string>> result = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(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<KeyValuePair<string, WagePerson>> list = new List<KeyValuePair<string, WagePerson>>();
+ list.Add(new KeyValuePair<string, WagePerson>("key1", new WagePerson
+ {
+ BirthDate = dateTime,
+ Department = "Department1",
+ LastModified = dateTime,
+ HourlyWage = 1
+ }));
+ list.Add(new KeyValuePair<string, WagePerson>("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<KeyValuePair<string, WagePerson>> result = JsonConvert.DeserializeObject<List<KeyValuePair<string, WagePerson>>>(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<string> existingStrings = (List<string>)existingValue;
+ List<string> newStrings = new List<string>(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<string>));
+ }
+ }
+
+ [Test]
+ public void StringListAppenderConverterTest()
+ {
+ Movie p = new Movie();
+ p.ReleaseCountries = new List<string> { "Existing" };
+
+ JsonConvert.PopulateObject("{'ReleaseCountries':['Appended']}", p, new JsonSerializerSettings
+ {
+ Converters = new List<JsonConverter> { 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<JsonConverter> { 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<string, object>();
+ reference.Add("$ref", "Persons");
+ reference.Add("$id", 1);
+
+ var child = new Dictionary<string, object>();
+ child.Add("_id", 2);
+ child.Add("Name", "Isabell");
+ child.Add("Father", reference);
+
+ var json = JsonConvert.SerializeObject(child);
+ JsonConvert.DeserializeObject<Dictionary<string, object>>(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<string, object>();
+ reference.Add("$ref", 1);
+ reference.Add("$id", 1);
+
+ var child = new Dictionary<string, object>();
+ child.Add("_id", 2);
+ child.Add("Name", "Isabell");
+ child.Add("Father", reference);
+
+ var json = JsonConvert.SerializeObject(child);
+ JsonConvert.DeserializeObject<Dictionary<string, object>>(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<ConstructorCompexIgnoredProperty>(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<ShouldSerializeTestClass>(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<SpecifiedTestClass>(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<SpecifiedTestClass>(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 = @"<?xml version=""1.0"" encoding=""utf-16""?>
+ //<OptionalOrder xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
+ // <FirstOrder>First</FirstOrder>
+ //</OptionalOrder>";
+
+ // 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 = @"<?xml version=""1.0"" encoding=""utf-16""?>
+ // //<OptionalOrder xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
+ // // <FirstOrder>First</FirstOrder>
+ // //</OptionalOrder>";
+
+ // // 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<FamilyDetails>(mikeString);
+
+ Console.WriteLine("mikeString specifies number of children: {0}", mike.NumberOfChildrenSpecified);
+
+ string mikeFullDisclosureString = "{\"Name\": \"Mike Person\", \"NumberOfChildren\": \"0\"}";
+ mike = JsonConvert.DeserializeObject<FamilyDetails>(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<DictionaryKey, string> dictionary = new Dictionary<DictionaryKey, string>();
+
+ 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<DictionaryKey, string> newDictionary =
+ JsonConvert.DeserializeObject<Dictionary<DictionaryKey, string>>(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<string>()
+ {
+ "One",
+ "2",
+ "III"
+ }, Formatting.Indented);
+
+ Assert.AreEqual(@"[
+ ""One"",
+ ""2"",
+ ""III""
+]", jsonText);
+
+ HashSet<string> d = JsonConvert.DeserializeObject<HashSet<string>>(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<StringDictionaryTestClass>(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<StructWithAttribute>(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<TimeZoneOffsetObject>(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<NullableDateTimeTestClass>("{\"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<string, object> newExpando = JsonConvert.DeserializeObject<ExpandoObject>(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<string, object> 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<decimal>("123456789876543.21");
+ Assert.AreEqual(123456789876543.21m, d);
+ }
+
+ [Test]
+ public void DeserializeNullableDecimalExact()
+ {
+ decimal? d = JsonConvert.DeserializeObject<decimal?>("123456789876543.21");
+ Assert.AreEqual(123456789876543.21m, d);
+ }
+
+ [Test]
+ public void DeserializeDecimalPropertyExact()
+ {
+ string json = "{Amount:123456789876543.21}";
+ Invoice i = JsonConvert.DeserializeObject<Invoice>(json);
+ Assert.AreEqual(123456789876543.21m, i.Amount);
+ }
+
+ [Test]
+ public void DeserializeDecimalArrayExact()
+ {
+ string json = "[123456789876543.21]";
+ IList<decimal> a = JsonConvert.DeserializeObject<IList<decimal>>(json);
+ Assert.AreEqual(123456789876543.21m, a[0]);
+ }
+
+ [Test]
+ public void DeserializeDecimalDictionaryExact()
+ {
+ string json = "{'Value':123456789876543.21}";
+ IDictionary<string, decimal> d = JsonConvert.DeserializeObject<IDictionary<string, decimal>>(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<VectorParent>(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<Base>(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<NullableStructPropertyClass>(
+ 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<Response>(json);
+
+ Assert.AreEqual("Success", deserializedResponse.Name);
+ Assert.IsTrue(deserializedResponse.Data.DeepEquals(response.Data));
+ }
+
+ public abstract class Test<T>
+ {
+ public abstract T Value { get; set; }
+ }
+
+ [JsonObject(MemberSerialization.OptIn)]
+ public class DecimalTest : Test<decimal>
+ {
+ 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<DecimalTest>(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<NonPublicConstructorWithJsonConstructor>("{}");
+ 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<PublicConstructorOverridenByJsonConstructor>("{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<MultipleParamatrizedConstructorsJsonConstructor>("{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<string> Enumerable { get; set; }
+ }
+
+ [Test]
+ public void DeserializeEnumerable()
+ {
+ EnumerableClass c = new EnumerableClass
+ {
+ Enumerable = new List<string> { "One", "Two", "Three" }
+ };
+
+ string json = JsonConvert.SerializeObject(c, Formatting.Indented);
+
+ Assert.AreEqual(@"{
+ ""Enumerable"": [
+ ""One"",
+ ""Two"",
+ ""Three""
+ ]
+}", json);
+
+ EnumerableClass c2 = JsonConvert.DeserializeObject<EnumerableClass>(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<DeserializeStringConvert>(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<decimal> 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<CommentTestClass>(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<DTOWithoutParameterisedConstructor>(json);
+ var withParameterisedConstructor = JsonConvert.DeserializeObject<DTOWithParameterisedConstructor>(json);
+ Assert.AreEqual(withoutParameterisedConstructor.B, withParameterisedConstructor.B);
+ }
+ }
+}
\ No newline at end of file