diff --git a/Src/Newtonsoft.Json.Tests/Documentation/ConvertingJsonAndXmlTests.cs b/Src/Newtonsoft.Json.Tests/Documentation/ConvertingJsonAndXmlTests.cs
new file mode 100644
index 00000000..e4b95731
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Documentation/ConvertingJsonAndXmlTests.cs
@@ -0,0 +1,137 @@
+#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
+
+#if !(NET35 || NET20 || PORTABLE)
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Dynamic;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Xml;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Linq;
+#if !NETFX_CORE
+using NUnit.Framework;
+#else
+using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
+using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
+using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
+#endif
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Tests.TestObjects;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
+
+namespace Newtonsoft.Json.Tests.Documentation
+{
+ public class ConvertingJsonAndXmlTests
+ {
+ public void SerializeXmlNode()
+ {
+ #region SerializeXmlNode
+ string xml = @"
+
+
+ Alan
+ http://www.google.com
+
+
+ Louis
+ http://www.yahoo.com
+
+ ";
+
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(xml);
+
+ string jsonText = JsonConvert.SerializeXmlNode(doc);
+ //{
+ // "?xml": {
+ // "@version": "1.0",
+ // "@standalone": "no"
+ // },
+ // "root": {
+ // "person": [
+ // {
+ // "@id": "1",
+ // "name": "Alan",
+ // "url": "http://www.google.com"
+ // },
+ // {
+ // "@id": "2",
+ // "name": "Louis",
+ // "url": "http://www.yahoo.com"
+ // }
+ // ]
+ // }
+ //}
+ #endregion
+ }
+
+ public void DeserializeXmlNode()
+ {
+ #region DeserializeXmlNode
+ string json = @"{
+ '?xml': {
+ '@version': '1.0',
+ '@standalone': 'no'
+ },
+ 'root': {
+ 'person': [
+ {
+ '@id': '1',
+ 'name': 'Alan',
+ 'url': 'http://www.google.com'
+ },
+ {
+ '@id': '2',
+ 'name': 'Louis',
+ 'url': 'http://www.yahoo.com'
+ }
+ ]
+ }
+ }";
+
+ XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json);
+ //
+ //
+ //
+ // Alan
+ // http://www.google.com
+ //
+ //
+ // Louis
+ // http://www.yahoo.com
+ //
+ //
+ #endregion
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Documentation/LinqToJsonTests.cs b/Src/Newtonsoft.Json.Tests/Documentation/LinqToJsonTests.cs
new file mode 100644
index 00000000..f316c4d1
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Documentation/LinqToJsonTests.cs
@@ -0,0 +1,341 @@
+#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
+
+#if !(NET35 || NET20 || PORTABLE)
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Dynamic;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Linq;
+#if !NETFX_CORE
+using NUnit.Framework;
+#else
+using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
+using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
+using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
+#endif
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Tests.TestObjects;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
+
+namespace Newtonsoft.Json.Tests.Documentation
+{
+ public class LinqToJsonTests
+ {
+ public void LinqToJsonCreateNormal()
+ {
+ #region LinqToJsonCreateNormal
+ JArray array = new JArray();
+ JValue text = new JValue("Manual text");
+ JValue date = new JValue(new DateTime(2000, 5, 23));
+
+ array.Add(text);
+ array.Add(date);
+
+ string json = array.ToString();
+ // [
+ // "Manual text",
+ // "\/Date(958996800000+1200)\/"
+ // ]
+ #endregion
+ }
+
+ public class Post
+ {
+ public string Title { get; set; }
+ public string Description { get; set; }
+ public string Link { get; set; }
+ public IList Categories { get; set; }
+ }
+
+ private List GetPosts()
+ {
+ return null;
+ }
+
+ public void LinqToJsonCreateDeclaratively()
+ {
+ #region LinqToJsonCreateDeclaratively
+ List posts = GetPosts();
+
+ JObject rss =
+ new JObject(
+ new JProperty("channel",
+ new JObject(
+ new JProperty("title", "James Newton-King"),
+ new JProperty("link", "http://james.newtonking.com"),
+ new JProperty("description", "James Newton-King's blog."),
+ new JProperty("item",
+ new JArray(
+ from p in posts
+ orderby p.Title
+ select new JObject(
+ new JProperty("title", p.Title),
+ new JProperty("description", p.Description),
+ new JProperty("link", p.Link),
+ new JProperty("category",
+ new JArray(
+ from c in p.Categories
+ select new JValue(c)))))))));
+
+ Console.WriteLine(rss.ToString());
+
+ //{
+ // "channel": {
+ // "title": "James Newton-King",
+ // "link": "http://james.newtonking.com",
+ // "description": "James Newton-King's blog.",
+ // "item": [
+ // {
+ // "title": "Json.NET 1.3 + New license + Now on CodePlex",
+ // "description": "Annoucing the release of Json.NET 1.3, the MIT license and the source being available on CodePlex",
+ // "link": "http://james.newtonking.com/projects/json-net.aspx",
+ // "category": [
+ // "Json.NET",
+ // "CodePlex"
+ // ]
+ // },
+ // {
+ // "title": "LINQ to JSON beta",
+ // "description": "Annoucing LINQ to JSON",
+ // "link": "http://james.newtonking.com/projects/json-net.aspx",
+ // "category": [
+ // "Json.NET",
+ // "LINQ"
+ // ]
+ // }
+ // ]
+ // }
+ //}
+ #endregion
+ }
+
+ public void LinqToJsonCreateFromObject()
+ {
+ List posts = null;
+
+ #region LinqToJsonCreateFromObject
+ JObject o = JObject.FromObject(new
+ {
+ channel = new
+ {
+ title = "James Newton-King",
+ link = "http://james.newtonking.com",
+ description = "James Newton-King's blog.",
+ item =
+ from p in posts
+ orderby p.Title
+ select new
+ {
+ title = p.Title,
+ description = p.Description,
+ link = p.Link,
+ category = p.Categories
+ }
+ }
+ });
+ #endregion
+ }
+
+ public void LinqToJsonCreateParse()
+ {
+ #region LinqToJsonCreateParse
+ string json = @"{
+ CPU: 'Intel',
+ Drives: [
+ 'DVD read/writer',
+ ""500 gigabyte hard drive""
+ ]
+ }";
+
+ JObject o = JObject.Parse(json);
+ #endregion
+ }
+
+ public void LinqToJsonQuerying()
+ {
+ JObject rss = new JObject();
+
+ #region LinqToJsonQuerying
+ var postTitles =
+ from p in rss["channel"]["item"].Children()
+ select (string)p["title"];
+
+ foreach (var item in postTitles)
+ {
+ Console.WriteLine(item);
+ }
+
+ //LINQ to JSON beta
+ //Json.NET 1.3 + New license + Now on CodePlex
+
+ var categories =
+ from c in rss["channel"]["item"].Children()["category"].Values()
+ group c by c into g
+ orderby g.Count() descending
+ select new { Category = g.Key, Count = g.Count() };
+
+ foreach (var c in categories)
+ {
+ Console.WriteLine(c.Category + " - Count: " + c.Count);
+ }
+
+ //Json.NET - Count: 2
+ //LINQ - Count: 1
+ //CodePlex - Count: 1
+ #endregion
+ }
+
+ #region LinqToJsonDeserializeObject
+ public class Shortie
+ {
+ public string Original { get; set; }
+ public string Shortened { get; set; }
+ public string Short { get; set; }
+ public ShortieException Error { get; set; }
+ }
+
+ public class ShortieException
+ {
+ public int Code { get; set; }
+ public string ErrorMessage { get; set; }
+ }
+ #endregion
+
+ public void LinqToJsonDeserializeExample()
+ {
+ #region LinqToJsonDeserializeExample
+ string jsonText = @"{
+ 'short': {
+ 'original': 'http://www.foo.com/',
+ 'short': 'krehqk',
+ 'error': {
+ 'code':0,
+ 'msg':'No action taken'
+ }
+ }";
+
+ JObject json = JObject.Parse(jsonText);
+
+ Shortie shortie = new Shortie
+ {
+ Original = (string)json["short"]["original"],
+ Short = (string)json["short"]["short"],
+ Error = new ShortieException
+ {
+ Code = (int)json["short"]["error"]["code"],
+ ErrorMessage = (string)json["short"]["error"]["msg"]
+ }
+ };
+
+ Console.WriteLine(shortie.Original);
+ // http://www.foo.com/
+
+ Console.WriteLine(shortie.Error.ErrorMessage);
+ // No action taken
+ #endregion
+ }
+
+ public void SelectTokenSimple()
+ {
+ JObject o = new JObject();
+
+ #region SelectTokenSimple
+ string name = (string)o.SelectToken("Manufacturers[0].Name");
+ #endregion
+ }
+
+ public void SelectTokenComplex()
+ {
+ #region SelectTokenComplex
+ JObject o = JObject.Parse(@"{
+ 'Stores': [
+ 'Lambton Quay',
+ 'Willis Street'
+ ],
+ 'Manufacturers': [
+ {
+ 'Name': 'Acme Co',
+ 'Products': [
+ {
+ 'Name': 'Anvil',
+ 'Price': 50
+ }
+ ]
+ },
+ {
+ 'Name': 'Contoso',
+ 'Products': [
+ {
+ 'Name': 'Elbow Grease',
+ 'Price': 99.95
+ },
+ {
+ 'Name': 'Headlight Fluid',
+ 'Price': 4
+ }
+ ]
+ }
+ ]
+ }");
+
+ string name = (string)o.SelectToken("Manufacturers[0].Name");
+ // Acme Co
+
+ decimal productPrice = (decimal)o.SelectToken("Manufacturers[0].Products[0].Price");
+ // 50
+
+ string productName = (string)o.SelectToken("Manufacturers[1].Products[0].Name");
+ // Elbow Grease
+ #endregion
+ }
+
+ public void SelectTokenLinq()
+ {
+ JObject o = new JObject();
+
+ #region SelectTokenLinq
+ IList storeNames = o.SelectToken("Stores").Select(s => (string)s).ToList();
+ // Lambton Quay
+ // Willis Street
+
+ IList firstProductNames = o["Manufacturers"].Select(m => (string)m.SelectToken("Products[1].Name")).ToList();
+ // null
+ // Headlight Fluid
+
+ decimal totalPrice = o["Manufacturers"].Sum(m => (decimal)m.SelectToken("Products[0].Price"));
+ // 149.95
+ #endregion
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Documentation/ReadingAndWritingJsonTests.cs b/Src/Newtonsoft.Json.Tests/Documentation/ReadingAndWritingJsonTests.cs
new file mode 100644
index 00000000..def2b0af
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Documentation/ReadingAndWritingJsonTests.cs
@@ -0,0 +1,109 @@
+#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
+
+#if !(NET35 || NET20 || PORTABLE)
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Dynamic;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Linq;
+#if !NETFX_CORE
+using NUnit.Framework;
+#else
+using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
+using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
+using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
+#endif
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Tests.TestObjects;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
+
+namespace Newtonsoft.Json.Tests.Documentation
+{
+ public class ReadingAndWritingJsonTests
+ {
+ public void ReadingAndWritingJsonText()
+ {
+ #region ReadingAndWritingJsonText
+ StringBuilder sb = new StringBuilder();
+ StringWriter sw = new StringWriter(sb);
+
+ using (JsonWriter writer = new JsonTextWriter(sw))
+ {
+ writer.Formatting = Formatting.Indented;
+
+ writer.WriteStartObject();
+ writer.WritePropertyName("CPU");
+ writer.WriteValue("Intel");
+ writer.WritePropertyName("PSU");
+ writer.WriteValue("500W");
+ writer.WritePropertyName("Drives");
+ writer.WriteStartArray();
+ writer.WriteValue("DVD read/writer");
+ writer.WriteComment("(broken)");
+ writer.WriteValue("500 gigabyte hard drive");
+ writer.WriteValue("200 gigabype hard drive");
+ writer.WriteEnd();
+ writer.WriteEndObject();
+ }
+
+ // {
+ // "CPU": "Intel",
+ // "PSU": "500W",
+ // "Drives": [
+ // "DVD read/writer"
+ // /*(broken)*/,
+ // "500 gigabyte hard drive",
+ // "200 gigabype hard drive"
+ // ]
+ // }
+ #endregion
+ }
+
+ public void ReadingAndWritingJsonLinq()
+ {
+ #region ReadingAndWritingJsonLinq
+ JObject o = new JObject(
+ new JProperty("Name", "John Smith"),
+ new JProperty("BirthDate", new DateTime(1983, 3, 20))
+ );
+
+ JsonSerializer serializer = new JsonSerializer();
+ Person p = (Person)serializer.Deserialize(new JTokenReader(o), typeof(Person));
+
+ Console.WriteLine(p.Name);
+ // John Smith
+ #endregion
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Documentation/SerializationTests.cs b/Src/Newtonsoft.Json.Tests/Documentation/SerializationTests.cs
new file mode 100644
index 00000000..908c48b8
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Documentation/SerializationTests.cs
@@ -0,0 +1,887 @@
+#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
+
+#if !(NET35 || NET20 || PORTABLE)
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Dynamic;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Linq;
+#if !NETFX_CORE
+using NUnit.Framework;
+#else
+using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
+using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
+using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
+#endif
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Tests.TestObjects;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
+
+namespace Newtonsoft.Json.Tests.Documentation
+{
+ public class SerializationTests
+ {
+ public void SerializeObject()
+ {
+ #region SerializeObject
+ 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": "2008-12-28T00:00:00",
+ // "Price": 3.99,
+ // "Sizes": [
+ // "Small",
+ // "Medium",
+ // "Large"
+ // ]
+ //}
+
+ Product deserializedProduct = JsonConvert.DeserializeObject(output);
+ #endregion
+ }
+
+ public void JsonSerializerToStream()
+ {
+ #region JsonSerializerToStream
+ 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}
+ }
+ #endregion
+ }
+
+ #region SerializationAttributes
+ [JsonObject(MemberSerialization.OptIn)]
+ public class Person
+ {
+ // "John Smith"
+ [JsonProperty]
+ public string Name { get; set; }
+
+ // "2000-12-15T22:11:03"
+ [JsonProperty]
+ public DateTime BirthDate { get; set; }
+
+ // new Date(976918263055)
+ [JsonProperty]
+ [JsonConverter(typeof(JavaScriptDateTimeConverter))]
+ public DateTime LastModified { get; set; }
+
+ // not serialized because mode is opt-in
+ public string Department { get; set; }
+ }
+ #endregion
+
+#region SerializationCallbacksObject
+public class SerializationEventTestObject
+{
+ // 2222
+ // This member is serialized and deserialized with no change.
+ public int Member1 { get; set; }
+
+ // The value of this field is set and reset during and
+ // after serialization.
+ public string Member2 { get; set; }
+
+ // This field is not serialized. The OnDeserializedAttribute
+ // is used to set the member value after serialization.
+ [JsonIgnore]
+ public string Member3 { get; set; }
+
+ // This field is set to null, but populated after deserialization.
+ public string Member4 { get; set; }
+
+ public SerializationEventTestObject()
+ {
+ Member1 = 11;
+ Member2 = "Hello World!";
+ Member3 = "This is a nonserialized value";
+ Member4 = null;
+ }
+
+ [OnSerializing]
+ internal void OnSerializingMethod(StreamingContext context)
+ {
+ Member2 = "This value went into the data file during serialization.";
+ }
+
+ [OnSerialized]
+ internal void OnSerializedMethod(StreamingContext context)
+ {
+ Member2 = "This value was reset after serialization.";
+ }
+
+ [OnDeserializing]
+ internal void OnDeserializingMethod(StreamingContext context)
+ {
+ Member3 = "This value was set during deserialization";
+ }
+
+ [OnDeserialized]
+ internal void OnDeserializedMethod(StreamingContext context)
+ {
+ Member4 = "This value was set after deserialization.";
+ }
+}
+#endregion
+
+ public void SerializationCallbacksExample()
+ {
+ #region SerializationCallbacksExample
+ SerializationEventTestObject obj = new SerializationEventTestObject();
+
+ Console.WriteLine(obj.Member1);
+ // 11
+ Console.WriteLine(obj.Member2);
+ // Hello World!
+ Console.WriteLine(obj.Member3);
+ // This is a nonserialized value
+ Console.WriteLine(obj.Member4);
+ // null
+
+ string json = JsonConvert.SerializeObject(obj, Formatting.Indented);
+ // {
+ // "Member1": 11,
+ // "Member2": "This value went into the data file during serialization.",
+ // "Member4": null
+ // }
+
+ Console.WriteLine(obj.Member1);
+ // 11
+ Console.WriteLine(obj.Member2);
+ // This value was reset after serialization.
+ Console.WriteLine(obj.Member3);
+ // This is a nonserialized value
+ Console.WriteLine(obj.Member4);
+ // null
+
+ obj = JsonConvert.DeserializeObject(json);
+
+ Console.WriteLine(obj.Member1);
+ // 11
+ Console.WriteLine(obj.Member2);
+ // This value went into the data file during serialization.
+ Console.WriteLine(obj.Member3);
+ // This value was set during deserialization
+ Console.WriteLine(obj.Member4);
+ // This value was set after deserialization.
+ #endregion
+ }
+
+ public void SerializationErrorHandling()
+ {
+ #region SerializationErrorHandling
+ List errors = new List();
+
+ List c = JsonConvert.DeserializeObject>(@"[
+ '2009-09-09T00:00:00Z',
+ 'I am not a date and will error!',
+ [
+ 1
+ ],
+ '1977-02-20T00:00:00Z',
+ null,
+ '2000-12-01T00:00:00Z'
+ ]",
+ new JsonSerializerSettings
+ {
+ Error = delegate(object sender, ErrorEventArgs args)
+ {
+ errors.Add(args.ErrorContext.Error.Message);
+ args.ErrorContext.Handled = true;
+ },
+ Converters = { new IsoDateTimeConverter() }
+ });
+
+ // 2009-09-09T00:00:00Z
+ // 1977-02-20T00:00:00Z
+ // 2000-12-01T00:00:00Z
+
+ // The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.
+ // Unexpected token parsing date. Expected String, got StartArray.
+ // Cannot convert null value to System.DateTime.
+ #endregion
+ }
+
+ public void SerializationErrorHandlingWithParent()
+ {
+ #region SerializationErrorHandlingWithParent
+ List errors = new List();
+
+ JsonSerializer serializer = new JsonSerializer();
+ serializer.Error += delegate(object sender, ErrorEventArgs args)
+ {
+ // only log an error once
+ if (args.CurrentObject == args.ErrorContext.OriginalObject)
+ errors.Add(args.ErrorContext.Error.Message);
+ };
+ #endregion
+ }
+
+ #region SerializationErrorHandlingAttributeObject
+ public class PersonError
+ {
+ private List _roles;
+
+ public string Name { get; set; }
+ public int Age { get; set; }
+ public List Roles
+ {
+ get
+ {
+ if (_roles == null)
+ throw new Exception("Roles not loaded!");
+
+ return _roles;
+ }
+ set { _roles = value; }
+ }
+ public string Title { get; set; }
+
+ [OnError]
+ internal void OnError(StreamingContext context, ErrorContext errorContext)
+ {
+ errorContext.Handled = true;
+ }
+ }
+ #endregion
+
+ public void SerializationErrorHandlingAttributeExample()
+ {
+ #region SerializationErrorHandlingAttributeExample
+ PersonError person = new PersonError
+ {
+ Name = "George Michael Bluth",
+ Age = 16,
+ Roles = null,
+ Title = "Mister Manager"
+ };
+
+ string json = JsonConvert.SerializeObject(person, Formatting.Indented);
+
+ Console.WriteLine(json);
+ //{
+ // "Name": "George Michael Bluth",
+ // "Age": 16,
+ // "Title": "Mister Manager"
+ //}
+ #endregion
+ }
+
+ public void PreservingObjectReferencesOff()
+ {
+ #region PreservingObjectReferencesOff
+ Person p = new Person
+ {
+ BirthDate = new DateTime(1980, 12, 23, 0, 0, 0, DateTimeKind.Utc),
+ LastModified = new DateTime(2009, 2, 20, 12, 59, 21, DateTimeKind.Utc),
+ Name = "James"
+ };
+
+ List people = new List();
+ people.Add(p);
+ people.Add(p);
+
+ string json = JsonConvert.SerializeObject(people, Formatting.Indented);
+ //[
+ // {
+ // "Name": "James",
+ // "BirthDate": "\/Date(346377600000)\/",
+ // "LastModified": "\/Date(1235134761000)\/"
+ // },
+ // {
+ // "Name": "James",
+ // "BirthDate": "\/Date(346377600000)\/",
+ // "LastModified": "\/Date(1235134761000)\/"
+ // }
+ //]
+ #endregion
+ }
+
+ public void PreservingObjectReferencesOn()
+ {
+ List people = new List();
+
+ #region PreservingObjectReferencesOn
+ string json = JsonConvert.SerializeObject(people, Formatting.Indented,
+ new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
+
+ //[
+ // {
+ // "$id": "1",
+ // "Name": "James",
+ // "BirthDate": "\/Date(346377600000)\/",
+ // "LastModified": "\/Date(1235134761000)\/"
+ // },
+ // {
+ // "$ref": "1"
+ // }
+ //]
+
+ List deserializedPeople = JsonConvert.DeserializeObject>(json,
+ new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
+
+ Console.WriteLine(deserializedPeople.Count);
+ // 2
+
+ Person p1 = deserializedPeople[0];
+ Person p2 = deserializedPeople[1];
+
+ Console.WriteLine(p1.Name);
+ // James
+ Console.WriteLine(p2.Name);
+ // James
+
+ bool equal = Object.ReferenceEquals(p1, p2);
+ // true
+ #endregion
+ }
+
+ #region PreservingObjectReferencesAttribute
+ [JsonObject(IsReference = true)]
+ public class EmployeeReference
+ {
+ public string Name { get; set; }
+ public EmployeeReference Manager { get; set; }
+ }
+ #endregion
+
+ #region CustomCreationConverterObject
+ public interface IPerson
+ {
+ string FirstName { get; set; }
+ string LastName { get; set; }
+ DateTime BirthDate { get; set; }
+ }
+
+ public class Employee : IPerson
+ {
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ public DateTime BirthDate { get; set; }
+
+ public string Department { get; set; }
+ public string JobTitle { get; set; }
+ }
+
+ public class PersonConverter : CustomCreationConverter
+ {
+ public override IPerson Create(Type objectType)
+ {
+ return new Employee();
+ }
+ }
+ #endregion
+
+ public void CustomCreationConverterExample()
+ {
+ string json = null;
+
+ #region CustomCreationConverterExample
+ //[
+ // {
+ // "FirstName": "Maurice",
+ // "LastName": "Moss",
+ // "BirthDate": "\/Date(252291661000)\/",
+ // "Department": "IT",
+ // "JobTitle": "Support"
+ // },
+ // {
+ // "FirstName": "Jen",
+ // "LastName": "Barber",
+ // "BirthDate": "\/Date(258771661000)\/",
+ // "Department": "IT",
+ // "JobTitle": "Manager"
+ // }
+ //]
+
+ List people = JsonConvert.DeserializeObject>(json, new PersonConverter());
+
+ IPerson person = people[0];
+
+ Console.WriteLine(person.GetType());
+ // Newtonsoft.Json.Tests.Employee
+
+ Console.WriteLine(person.FirstName);
+ // Maurice
+
+ Employee employee = (Employee)person;
+
+ Console.WriteLine(employee.JobTitle);
+ // Support
+ #endregion
+ }
+
+ public void ContractResolver()
+ {
+ #region ContractResolver
+ Product product = new Product
+ {
+ ExpiryDate = new DateTime(2010, 12, 20, 18, 1, 0, DateTimeKind.Utc),
+ Name = "Widget",
+ Price = 9.99m,
+ Sizes = new[] { "Small", "Medium", "Large" }
+ };
+
+ string json =
+ JsonConvert.SerializeObject(
+ product,
+ Formatting.Indented,
+ new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }
+ );
+
+ //{
+ // "name": "Widget",
+ // "expiryDate": "\/Date(1292868060000)\/",
+ // "price": 9.99,
+ // "sizes": [
+ // "Small",
+ // "Medium",
+ // "Large"
+ // ]
+ //}
+ #endregion
+ }
+
+ public void SerializingCollectionsSerializing()
+ {
+ #region SerializingCollectionsSerializing
+ Product p1 = new Product
+ {
+ Name = "Product 1",
+ Price = 99.95m,
+ ExpiryDate = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc),
+ };
+ Product p2 = new Product
+ {
+ Name = "Product 2",
+ Price = 12.50m,
+ ExpiryDate = new DateTime(2009, 7, 31, 0, 0, 0, DateTimeKind.Utc),
+ };
+
+ List products = new List();
+ products.Add(p1);
+ products.Add(p2);
+
+ string json = JsonConvert.SerializeObject(products, Formatting.Indented);
+ //[
+ // {
+ // "Name": "Product 1",
+ // "ExpiryDate": "\/Date(978048000000)\/",
+ // "Price": 99.95,
+ // "Sizes": null
+ // },
+ // {
+ // "Name": "Product 2",
+ // "ExpiryDate": "\/Date(1248998400000)\/",
+ // "Price": 12.50,
+ // "Sizes": null
+ // }
+ //]
+ #endregion
+ }
+
+ public void SerializingCollectionsDeserializing()
+ {
+ #region SerializingCollectionsDeserializing
+ string json = @"[
+ {
+ 'Name': 'Product 1',
+ 'ExpiryDate': '\/Date(978048000000)\/',
+ 'Price': 99.95,
+ 'Sizes': null
+ },
+ {
+ 'Name': 'Product 2',
+ 'ExpiryDate': '\/Date(1248998400000)\/',
+ 'Price': 12.50,
+ 'Sizes': null
+ }
+ ]";
+
+ List products = JsonConvert.DeserializeObject>(json);
+
+ Console.WriteLine(products.Count);
+ // 2
+
+ Product p1 = products[0];
+
+ Console.WriteLine(p1.Name);
+ // Product 1
+ #endregion
+ }
+
+ public void SerializingCollectionsDeserializingDictionaries()
+ {
+ #region SerializingCollectionsDeserializingDictionaries
+ string json = @"{""key1"":""value1"",""key2"":""value2""}";
+
+ Dictionary values = JsonConvert.DeserializeObject>(json);
+
+ Console.WriteLine(values.Count);
+ // 2
+
+ Console.WriteLine(values["key1"]);
+ // value1
+ #endregion
+ }
+
+ #region SerializingDatesInJson
+ public class LogEntry
+ {
+ public string Details { get; set; }
+ public DateTime LogDate { get; set; }
+ }
+
+ public void WriteJsonDates()
+ {
+ LogEntry entry = new LogEntry
+ {
+ LogDate = new DateTime(2009, 2, 15, 0, 0, 0, DateTimeKind.Utc),
+ Details = "Application started."
+ };
+
+ // default as of Json.NET 4.5
+ string isoJson = JsonConvert.SerializeObject(entry);
+ // {"Details":"Application started.","LogDate":"2009-02-15T00:00:00Z"}
+
+ JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings
+ {
+ DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
+ };
+ string microsoftJson = JsonConvert.SerializeObject(entry, microsoftDateFormatSettings);
+ // {"Details":"Application started.","LogDate":"\/Date(1234656000000)\/"}
+
+ string javascriptJson = JsonConvert.SerializeObject(entry, new JavaScriptDateTimeConverter());
+ // {"Details":"Application started.","LogDate":new Date(1234656000000)}
+ }
+ #endregion
+
+ #region ReducingSerializedJsonSizeOptOut
+ public class Car
+ {
+ // included in JSON
+ public string Model { get; set; }
+ public DateTime Year { get; set; }
+ public List Features { get; set; }
+
+ // ignored
+ [JsonIgnore]
+ public DateTime LastModified { get; set; }
+ }
+ #endregion
+
+ #region ReducingSerializedJsonSizeOptIn
+ [DataContract]
+ public class Computer
+ {
+ // included in JSON
+ [DataMember]
+ public string Name { get; set; }
+ [DataMember]
+ public decimal SalePrice { get; set; }
+
+ // ignored
+ public string Manufacture { get; set; }
+ public int StockCount { get; set; }
+ public decimal WholeSalePrice { get; set; }
+ public DateTime NextShipmentDate { get; set; }
+ }
+ #endregion
+
+ #region ReducingSerializedJsonSizeNullValueHandlingObject
+ public class Movie
+ {
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public string Classification { get; set; }
+ public string Studio { get; set; }
+ public DateTime? ReleaseDate { get; set; }
+ public List ReleaseCountries { get; set; }
+ }
+ #endregion
+
+ public void ReducingSerializedJsonSizeNullValueHandlingExample()
+ {
+ #region ReducingSerializedJsonSizeNullValueHandlingExample
+ Movie movie = new Movie();
+ movie.Name = "Bad Boys III";
+ movie.Description = "It's no Bad Boys";
+
+ string included = JsonConvert.SerializeObject(movie,
+ Formatting.Indented,
+ new JsonSerializerSettings { });
+
+ // {
+ // "Name": "Bad Boys III",
+ // "Description": "It's no Bad Boys",
+ // "Classification": null,
+ // "Studio": null,
+ // "ReleaseDate": null,
+ // "ReleaseCountries": null
+ // }
+
+ string ignored = JsonConvert.SerializeObject(movie,
+ Formatting.Indented,
+ new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
+
+ // {
+ // "Name": "Bad Boys III",
+ // "Description": "It's no Bad Boys"
+ // }
+ #endregion
+ }
+
+ #region ReducingSerializedJsonSizeDefaultValueHandlingObject
+ public class Invoice
+ {
+ public string Company { get; set; }
+ public decimal Amount { get; set; }
+
+ // false is default value of bool
+ public bool Paid { get; set; }
+ // null is default value of nullable
+ public DateTime? PaidDate { get; set; }
+
+ // customize default values
+ [DefaultValue(30)]
+ public int FollowUpDays { get; set; }
+ [DefaultValue("")]
+ public string FollowUpEmailAddress { get; set; }
+ }
+ #endregion
+
+ public void ReducingSerializedJsonSizeDefaultValueHandlingExample()
+ {
+ #region ReducingSerializedJsonSizeDefaultValueHandlingExample
+ Invoice invoice = new Invoice
+ {
+ Company = "Acme Ltd.",
+ Amount = 50.0m,
+ Paid = false,
+ FollowUpDays = 30,
+ FollowUpEmailAddress = string.Empty,
+ PaidDate = null
+ };
+
+ string included = JsonConvert.SerializeObject(invoice,
+ Formatting.Indented,
+ new JsonSerializerSettings { });
+
+ // {
+ // "Company": "Acme Ltd.",
+ // "Amount": 50.0,
+ // "Paid": false,
+ // "PaidDate": null,
+ // "FollowUpDays": 30,
+ // "FollowUpEmailAddress": ""
+ // }
+
+ string ignored = JsonConvert.SerializeObject(invoice,
+ Formatting.Indented,
+ new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
+
+ // {
+ // "Company": "Acme Ltd.",
+ // "Amount": 50.0
+ // }
+ #endregion
+ }
+
+ #region ReducingSerializedJsonSizeContractResolverObject
+ public class DynamicContractResolver : DefaultContractResolver
+ {
+ private readonly char _startingWithChar;
+ public DynamicContractResolver(char startingWithChar)
+ {
+ _startingWithChar = startingWithChar;
+ }
+
+ protected override IList CreateProperties(Type type, MemberSerialization memberSerialization)
+ {
+ IList properties = base.CreateProperties(type, memberSerialization);
+
+ // only serializer properties that start with the specified character
+ properties =
+ properties.Where(p => p.PropertyName.StartsWith(_startingWithChar.ToString())).ToList();
+
+ return properties;
+ }
+ }
+
+ public class Book
+ {
+ public string BookName { get; set; }
+ public decimal BookPrice { get; set; }
+ public string AuthorName { get; set; }
+ public int AuthorAge { get; set; }
+ public string AuthorCountry { get; set; }
+ }
+ #endregion
+
+ public void ReducingSerializedJsonSizeContractResolverExample()
+ {
+ #region ReducingSerializedJsonSizeContractResolverExample
+ Book book = new Book
+ {
+ BookName = "The Gathering Storm",
+ BookPrice = 16.19m,
+ AuthorName = "Brandon Sanderson",
+ AuthorAge = 34,
+ AuthorCountry = "United States of America"
+ };
+
+ string startingWithA = JsonConvert.SerializeObject(book, Formatting.Indented,
+ new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('A') });
+
+ // {
+ // "AuthorName": "Brandon Sanderson",
+ // "AuthorAge": 34,
+ // "AuthorCountry": "United States of America"
+ // }
+
+ string startingWithB = JsonConvert.SerializeObject(book, Formatting.Indented,
+ new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('B') });
+
+ // {
+ // "BookName": "The Gathering Storm",
+ // "BookPrice": 16.19
+ // }
+ #endregion
+ }
+
+ #region SerializingPartialJsonFragmentsObject
+ public class SearchResult
+ {
+ public string Title { get; set; }
+ public string Content { get; set; }
+ public string Url { get; set; }
+ }
+ #endregion
+
+ public void SerializingPartialJsonFragmentsExample()
+ {
+ #region SerializingPartialJsonFragmentsExample
+ string googleSearchText = @"{
+ 'responseData': {
+ 'results': [
+ {
+ 'GsearchResultClass': 'GwebSearch',
+ 'unescapedUrl': 'http://en.wikipedia.org/wiki/Paris_Hilton',
+ 'url': 'http://en.wikipedia.org/wiki/Paris_Hilton',
+ 'visibleUrl': 'en.wikipedia.org',
+ 'cacheUrl': 'http://www.google.com/search?q=cache:TwrPfhd22hYJ:en.wikipedia.org',
+ 'title': 'Paris Hilton - Wikipedia, the free encyclopedia',
+ 'titleNoFormatting': 'Paris Hilton - Wikipedia, the free encyclopedia',
+ 'content': '[1] In 2006, she released her debut album...'
+ },
+ {
+ 'GsearchResultClass': 'GwebSearch',
+ 'unescapedUrl': 'http://www.imdb.com/name/nm0385296/',
+ 'url': 'http://www.imdb.com/name/nm0385296/',
+ 'visibleUrl': 'www.imdb.com',
+ 'cacheUrl': 'http://www.google.com/search?q=cache:1i34KkqnsooJ:www.imdb.com',
+ 'title': 'Paris Hilton',
+ 'titleNoFormatting': 'Paris Hilton',
+ 'content': 'Self: Zoolander. Socialite Paris Hilton...'
+ }
+ ],
+ 'cursor': {
+ 'pages': [
+ {
+ 'start': '0',
+ 'label': 1
+ },
+ {
+ 'start': '4',
+ 'label': 2
+ },
+ {
+ 'start': '8',
+ 'label': 3
+ },
+ {
+ 'start': '12',
+ 'label': 4
+ }
+ ],
+ 'estimatedResultCount': '59600000',
+ 'currentPageIndex': 0,
+ 'moreResultsUrl': 'http://www.google.com/search?oe=utf8&ie=utf8...'
+ }
+ },
+ 'responseDetails': null,
+ 'responseStatus': 200
+ }";
+
+ JObject googleSearch = JObject.Parse(googleSearchText);
+
+ // get JSON result objects into a list
+ IList results = googleSearch["responseData"]["results"].Children().ToList();
+
+ // serialize JSON results into .NET objects
+ IList searchResults = new List();
+ foreach (JToken result in results)
+ {
+ SearchResult searchResult = JsonConvert.DeserializeObject(result.ToString());
+ searchResults.Add(searchResult);
+ }
+
+ // Title = Paris Hilton - Wikipedia, the free encyclopedia
+ // Content = [1] In 2006, she released her debut album...
+ // Url = http://en.wikipedia.org/wiki/Paris_Hilton
+
+ // Title = Paris Hilton
+ // Content = Self: Zoolander. Socialite Paris Hilton...
+ // Url = http://www.imdb.com/name/nm0385296/
+ #endregion
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
index ce3d7662..c8b7eb2a 100644
--- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
+++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
@@ -72,5 +72,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
#if !PocketPC
-[assembly: AssemblyFileVersion("4.5.7.15121")]
+[assembly: AssemblyFileVersion("4.5.7.15122")]
#endif
diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs
index 2c8177c2..963a32a8 100644
--- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs
+++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs
@@ -90,7 +90,7 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
#if !PocketPC
-[assembly: AssemblyFileVersion("4.5.7.15121")]
+[assembly: AssemblyFileVersion("4.5.7.15122")]
#endif
[assembly: CLSCompliant(true)]