All files
[pithos-ms-client] / trunk / Libraries / Json40r2 / Source / Src / Newtonsoft.Json.Tests / Serialization / JsonSerializerTest.cs
diff --git a/trunk/Libraries/Json40r2/Source/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/trunk/Libraries/Json40r2/Source/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
new file mode 100644 (file)
index 0000000..25d05eb
--- /dev/null
@@ -0,0 +1,4314 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+#if !SILVERLIGHT && !PocketPC && !NET20
+using System.ComponentModel.DataAnnotations;
+using System.Configuration;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Web.Script.Serialization;
+#endif
+using System.Text;
+using NUnit.Framework;
+using Newtonsoft.Json;
+using System.IO;
+using System.Collections;
+using System.Xml;
+using System.Xml.Serialization;
+using System.Collections.ObjectModel;
+using Newtonsoft.Json.Linq;
+using System.Linq;
+using Newtonsoft.Json.Converters;
+#if !PocketPC && !NET20 && !WINDOWS_PHONE
+using System.Runtime.Serialization.Json;
+#endif
+using Newtonsoft.Json.Tests.TestObjects;
+using System.Runtime.Serialization;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+using System.Reflection;
+#if !NET20 && !SILVERLIGHT
+using System.Xml.Linq;
+using System.Text.RegularExpressions;
+using System.Collections.Specialized;
+using System.Linq.Expressions;
+#endif
+#if !(NET35 || NET20 || WINDOWS_PHONE)
+using System.Dynamic;
+using System.ComponentModel;
+#endif
+
+namespace Newtonsoft.Json.Tests.Serialization
+{
+  public class JsonSerializerTest : TestFixtureBase
+  {
+    [Test]
+    public void PersonTypedObjectDeserialization()
+    {
+      Store store = new Store();
+
+      string jsonText = JsonConvert.SerializeObject(store);
+
+      Store deserializedStore = (Store)JsonConvert.DeserializeObject(jsonText, typeof(Store));
+
+      Assert.AreEqual(store.Establised, deserializedStore.Establised);
+      Assert.AreEqual(store.product.Count, deserializedStore.product.Count);
+
+      Console.WriteLine(jsonText);
+    }
+
+    [Test]
+    public void TypedObjectDeserialization()
+    {
+      Product product = new Product();
+
+      product.Name = "Apple";
+      product.ExpiryDate = new DateTime(2008, 12, 28);
+      product.Price = 3.99M;
+      product.Sizes = new string[] { "Small", "Medium", "Large" };
+
+      string output = JsonConvert.SerializeObject(product);
+      //{
+      //  "Name": "Apple",
+      //  "ExpiryDate": "\/Date(1230375600000+1300)\/",
+      //  "Price": 3.99,
+      //  "Sizes": [
+      //    "Small",
+      //    "Medium",
+      //    "Large"
+      //  ]
+      //}
+
+      Product deserializedProduct = (Product)JsonConvert.DeserializeObject(output, typeof(Product));
+
+      Assert.AreEqual("Apple", deserializedProduct.Name);
+      Assert.AreEqual(new DateTime(2008, 12, 28), deserializedProduct.ExpiryDate);
+      Assert.AreEqual(3.99, deserializedProduct.Price);
+      Assert.AreEqual("Small", deserializedProduct.Sizes[0]);
+      Assert.AreEqual("Medium", deserializedProduct.Sizes[1]);
+      Assert.AreEqual("Large", deserializedProduct.Sizes[2]);
+    }
+
+    //[Test]
+    //public void Advanced()
+    //{
+    //  Product product = new Product();
+    //  product.ExpiryDate = new DateTime(2008, 12, 28);
+
+    //  JsonSerializer serializer = new JsonSerializer();
+    //  serializer.Converters.Add(new JavaScriptDateTimeConverter());
+    //  serializer.NullValueHandling = NullValueHandling.Ignore;
+
+    //  using (StreamWriter sw = new StreamWriter(@"c:\json.txt"))
+    //  using (JsonWriter writer = new JsonTextWriter(sw))
+    //  {
+    //    serializer.Serialize(writer, product);
+    //    // {"ExpiryDate":new Date(1230375600000),"Price":0}
+    //  }
+    //}
+
+    [Test]
+    public void JsonConvertSerializer()
+    {
+      string value = @"{""Name"":""Orange"", ""Price"":3.99, ""ExpiryDate"":""01/24/2010 12:00:00""}";
+
+      Product p = JsonConvert.DeserializeObject(value, typeof(Product)) as Product;
+
+      Assert.AreEqual("Orange", p.Name);
+      Assert.AreEqual(new DateTime(2010, 1, 24, 12, 0, 0), p.ExpiryDate);
+      Assert.AreEqual(3.99, p.Price);
+    }
+
+    [Test]
+    public void DeserializeJavaScriptDate()
+    {
+      DateTime dateValue = new DateTime(2010, 3, 30);
+      Dictionary<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&#45;marketing&#45;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&#45;marketing&#45;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