From d92b8ceeb56d938887e1a12b03f8b393b32ecbc8 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 31 Oct 2012 13:24:47 +1300 Subject: [PATCH] -Documentation --- .gitignore | 5 +- Doc/ConditionalProperties.aml | 41 ++++ Doc/ContractResolver.aml | 123 ++++++------ Doc/Performance.aml | 166 ++++++++-------- Doc/doc.content | 55 +++--- Doc/doc.shfbproj | 5 +- .../ConditionalPropertiesTests.cs | 177 ++++++++++++++++++ .../Documentation/PerformanceTests.cs | 5 +- .../Newtonsoft.Json.Tests.csproj | 1 + .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- 11 files changed, 413 insertions(+), 169 deletions(-) create mode 100644 Doc/ConditionalProperties.aml create mode 100644 Src/Newtonsoft.Json.Tests/Documentation/ConditionalPropertiesTests.cs diff --git a/.gitignore b/.gitignore index cd628f1a..646c93b1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,7 @@ TestResults/ AppPackages/ *.suo -*.user \ No newline at end of file +*.user +_ReSharper.* +*.ReSharper.user +*.resharper.user \ No newline at end of file diff --git a/Doc/ConditionalProperties.aml b/Doc/ConditionalProperties.aml new file mode 100644 index 00000000..ba904a51 --- /dev/null +++ b/Doc/ConditionalProperties.aml @@ -0,0 +1,41 @@ + + + + + Json.NET has the ability to conditionally serialize properties by placing a ShouldSerialize method on a class. + This funtionality is similar to the +XmlSerializer ShouldSerialize feature +http://msdn.microsoft.com/en-us/library/53b8022e.aspx +_blank +. + +
+ ShouldSerialize + + To conditionally serialize a property add a boolean method with the same name as the property and then prefixed the method name + with ShouldSerialize. The result of the method determines whether the property is serialized. If the method returns true then the + property will be serialized, if it returns false and the property will be skipped. + + + + + +
+
+ IContractResolver + + ShouldSerialize can also be set using an T:Newtonsoft.Json.Serialization.IContractResolver. + Conditionally serializing a property using an IContractResolver is useful if you don't want to place a ShouldSerialize method on a class + or you didn't declare the class and are unable to. + + + + +
+ + T:Newtonsoft.Json.JsonSerializer + T:Newtonsoft.Json.Serialization.IContractResolver + M:Newtonsoft.Json.Serialization.JsonProperty.ShouldSerialize + +
+
\ No newline at end of file diff --git a/Doc/ContractResolver.aml b/Doc/ContractResolver.aml index cd31ee1d..4589c6d5 100644 --- a/Doc/ContractResolver.aml +++ b/Doc/ContractResolver.aml @@ -1,54 +1,71 @@ - - - - - - The T:Newtonsoft.Json.Serialization.IContractResolver - interface provides a way to customize how the - JsonSerializer serializes and deserializes .NET objects to JSON. - Implementing the IContractResolver interface and then assigning an - instance to a JsonSerializer lets you control whether the object is - serialized as a JSON object or JSON array, what object members should be - serialized, how they are serialized and what they are called. - - -
- DefaultContractResolver - - - The T:Newtonsoft.Json.Serialization.DefaultContractResolver - is the default resolver used by the - serializer. It provides many avenues of extensibility in the form of - virtual methods that can be overriden. - -
-
- CamelCasePropertyNamesContractResolver - - - T:Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver - inherits from DefaultContractResolver and simply overrides the JSON - property name to be written in -camelcase -http://en.wikipedia.org/wiki/CamelCase -_blank -. - - - -
- - T:Newtonsoft.Json.Serialization.IContractResolver - T:Newtonsoft.Json.Serialization.DefaultContractResolver - T:Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver - -
+ + + + + + The T:Newtonsoft.Json.Serialization.IContractResolver + interface provides a way to customize how the + JsonSerializer serializes and deserializes .NET objects to JSON. + Implementing the IContractResolver interface and then assigning an + instance to a JsonSerializer lets you control whether the object is + serialized as a JSON object or JSON array, what object members should be + serialized, how they are serialized and what they are called. + + +
+ DefaultContractResolver + + + The T:Newtonsoft.Json.Serialization.DefaultContractResolver + is the default resolver used by the + serializer. It provides many avenues of extensibility in the form of + virtual methods that can be overriden. + +
+
+ CamelCasePropertyNamesContractResolver + + + T:Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver + inherits from DefaultContractResolver and simply overrides the JSON + property name to be written in +camelcase +http://en.wikipedia.org/wiki/CamelCase +_blank +. + + + +
+
+ Custom Examples + + Setting a T:Newtonsoft.Json.JsonConverter on a type + using an IContractResolver. + + + + + Conditionally serializing properties + ConditionalProperties.htm + _self + using an IContractResolver. + + + +
+ + T:Newtonsoft.Json.Serialization.IContractResolver + T:Newtonsoft.Json.Serialization.DefaultContractResolver + T:Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver + +
\ No newline at end of file diff --git a/Doc/Performance.aml b/Doc/Performance.aml index ce89d2ff..0115f609 100644 --- a/Doc/Performance.aml +++ b/Doc/Performance.aml @@ -1,84 +1,84 @@ - - - - - Out of the box Json.NET is faster than DataContractJsonSerializer and JavaScriptSerializer. - Here are some tips to make it go even faster. - -
- Optimize Memory Usage - - To keep an application consistantly fast it is important to minimize the - amount of time the .NET framework spends performing -garbage collection -http://msdn.microsoft.com/en-us/library/ms973837.aspx -_blank -. - Allocating too many objects, or allocating very large objects can slow down or even - halt an application while garbage collection is in progress. - - To minimize memory usage and the number of objects allocated Json.NET supports - serializing and deserializing directly to a stream. Reading or writing JSON a piece at a time instead of having - the entire JSON string loaded into memory is especially important when working with JSON - documents greater than 85kb in size to avoid the JSON string ending up in the -large object heap -http://msdn.microsoft.com/en-us/magazine/cc534993.aspx -_blank -. - - - - - -
-
- JsonConverters - - Passing a T:Newtonsoft.Json.JsonConverter to SerializeObject or DeserializeObject provides a simple way to completely - change how an object is serialized. There is however a small overhead; the CanConvert method is called for every - type to check whether serialization should be handled by that JsonConverter. - There are a couple of ways to continue to use JsonConverters without any overhead. The simplest way - is to specify the JsonConverter using the T:Newtonsoft.Json.JsonConverterAttribute. This attribute tells the serializer - to always use that converter when serializing and deserializing the type, without the check. - - - - If the class you want to convert isn't your own and you're unable to use an attribute a JsonConverter can still be used by - creating your own T:Newtonsoft.Json.Serialization.IContractResolver. - - - - The IContractResolver in the example above will set all DateTimes to use the JavaScriptDateConverter. - -
-
- Manually Serialize - - The absolute fastest way to read and write JSON is to use JsonTextReader and JsonTextWriter directly. Using a reader or writer - directly skips any of the overhead from a serializer such as reflection. - - - - If performance is important and you don't mind more code to get it then this is your best choice. - -
-
- Benchmarks - - - - - Json.NET Performance - - - -
- - T:Newtonsoft.Json.JsonSerializer - T:Newtonsoft.Json.JsonConverter - T:Newtonsoft.Json.JsonConverterAttribute - T:Newtonsoft.Json.JsonTextWriter - T:Newtonsoft.Json.JsonTextReader - -
+ + + + + Out of the box Json.NET is faster than DataContractJsonSerializer and JavaScriptSerializer. + Here are some tips to make it go even faster. + +
+ Optimize Memory Usage + + To keep an application consistantly fast it is important to minimize the + amount of time the .NET framework spends performing +garbage collection +http://msdn.microsoft.com/en-us/library/ms973837.aspx +_blank +. + Allocating too many objects, or allocating very large objects can slow down or even + halt an application while garbage collection is in progress. + + To minimize memory usage and the number of objects allocated Json.NET supports + serializing and deserializing directly to a stream. Reading or writing JSON a piece at a time instead of having + the entire JSON string loaded into memory is especially important when working with JSON + documents greater than 85kb in size to avoid the JSON string ending up in the +large object heap +http://msdn.microsoft.com/en-us/magazine/cc534993.aspx +_blank +. + + + + + +
+
+ JsonConverters + + Passing a T:Newtonsoft.Json.JsonConverter to SerializeObject or DeserializeObject provides a simple way to completely + change how an object is serialized. There is however a small overhead; the CanConvert method is called for every + value to check whether serialization should be handled by that JsonConverter. + There are a couple of ways to continue to use JsonConverters without any overhead. The simplest way + is to specify the JsonConverter using the T:Newtonsoft.Json.JsonConverterAttribute. This attribute tells the serializer + to always use that converter when serializing and deserializing the type, without the check. + + + + If the class you want to convert isn't your own and you're unable to use an attribute a JsonConverter can still be used by + creating your own T:Newtonsoft.Json.Serialization.IContractResolver. + + + + The IContractResolver in the example above will set all DateTimes to use the JavaScriptDateConverter. + +
+
+ Manually Serialize + + The absolute fastest way to read and write JSON is to use JsonTextReader/JsonTextWriter directly to manually serialize types. + Using a reader or writer directly skips any of the overhead from a serializer such as reflection. + + + + If performance is important and you don't mind more code to get it then this is your best choice. + +
+
+ Benchmarks + + + + + Json.NET Performance + + + +
+ + T:Newtonsoft.Json.JsonSerializer + T:Newtonsoft.Json.JsonConverter + T:Newtonsoft.Json.JsonConverterAttribute + T:Newtonsoft.Json.JsonTextWriter + T:Newtonsoft.Json.JsonTextReader + +
\ No newline at end of file diff --git a/Doc/doc.content b/Doc/doc.content index 47ec2e05..1b220554 100644 --- a/Doc/doc.content +++ b/Doc/doc.content @@ -1,28 +1,29 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Doc/doc.shfbproj b/Doc/doc.shfbproj index 467a9577..c7d9481b 100644 --- a/Doc/doc.shfbproj +++ b/Doc/doc.shfbproj @@ -8,7 +8,7 @@ AnyCPU 2.0 {fd19f68e-72c8-4576-9775-b4480b0db686} - 1.9.3.0 + 1.9.5.0 Documentation @@ -32,7 +32,7 @@ Website - .NET 4.0.30319 + .NET Framework 4.0 Json.NET - Documentation vs2005 MemberName @@ -137,6 +137,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Documentation/ConditionalPropertiesTests.cs b/Src/Newtonsoft.Json.Tests/Documentation/ConditionalPropertiesTests.cs new file mode 100644 index 00000000..7ae89735 --- /dev/null +++ b/Src/Newtonsoft.Json.Tests/Documentation/ConditionalPropertiesTests.cs @@ -0,0 +1,177 @@ +#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.Net; +using System.Reflection; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +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; + +namespace Newtonsoft.Json.Tests.Documentation +{ + public class Employee + { + public string Name { get; set; } + public Employee Manager { get; set; } + } + + #region ShouldSerializeContractResolver + public class ShouldSerializeContractResolver : DefaultContractResolver + { + public new static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver(); + + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + JsonProperty property = base.CreateProperty(member, memberSerialization); + + if (property.DeclaringType == typeof(Employee) && property.PropertyName == "Manager") + { + property.ShouldSerialize = + instance => + { + Employee e = (Employee) instance; + return e.Manager != e; + }; + } + + return property; + } + } + #endregion + + [TestFixture] + public class ConditionalPropertiesTests : TestFixtureBase + { + #region EmployeeShouldSerializeExample + public class Employee + { + public string Name { get; set; } + public Employee Manager { get; set; } + + public bool ShouldSerializeManager() + { + // don't serialize the Manager property if an employee is their own manager + return (Manager != this); + } + } + #endregion + + [Test] + public void ShouldSerializeClassTest() + { + #region ShouldSerializeClassTest + Employee joe = new Employee(); + joe.Name = "Joe Employee"; + Employee mike = new Employee(); + mike.Name = "Mike Manager"; + + joe.Manager = mike; + + // mike is his own manager + // ShouldSerialize will skip this property + mike.Manager = mike; + + string json = JsonConvert.SerializeObject(new[] { joe, mike }, Formatting.Indented); + // [ + // { + // "Name": "Joe Employee", + // "Manager": { + // "Name": "Mike Manager" + // } + // }, + // { + // "Name": "Mike Manager" + // } + // ] + #endregion + + Assert.AreEqual(@"[ + { + ""Name"": ""Joe Employee"", + ""Manager"": { + ""Name"": ""Mike Manager"" + } + }, + { + ""Name"": ""Mike Manager"" + } +]", json); + } + + [Test] + public void ShouldSerializeContractResolverTest() + { + Newtonsoft.Json.Tests.Documentation.Employee joe = new Newtonsoft.Json.Tests.Documentation.Employee(); + joe.Name = "Joe Employee"; + Newtonsoft.Json.Tests.Documentation.Employee mike = new Newtonsoft.Json.Tests.Documentation.Employee(); + mike.Name = "Mike Manager"; + + joe.Manager = mike; + mike.Manager = mike; + + string json = JsonConvert.SerializeObject( + new[] {joe, mike}, + Formatting.Indented, + new JsonSerializerSettings + { + ContractResolver = ShouldSerializeContractResolver.Instance + }); + + Assert.AreEqual(@"[ + { + ""Name"": ""Joe Employee"", + ""Manager"": { + ""Name"": ""Mike Manager"" + } + }, + { + ""Name"": ""Mike Manager"" + } +]", json); + + } + } +} +#endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Documentation/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/Documentation/PerformanceTests.cs index b0058366..eafc15eb 100644 --- a/Src/Newtonsoft.Json.Tests/Documentation/PerformanceTests.cs +++ b/Src/Newtonsoft.Json.Tests/Documentation/PerformanceTests.cs @@ -80,10 +80,13 @@ namespace Newtonsoft.Json.Tests.Documentation #region JsonConverterContractResolver public class ConverterContractResolver : DefaultContractResolver { + public new static readonly ConverterContractResolver Instance = new ConverterContractResolver(); + protected override JsonContract CreateContract(Type objectType) { JsonContract contract = base.CreateContract(objectType); + // this will only be called once and then cached if (objectType == typeof(DateTime) || objectType == typeof(DateTimeOffset)) contract.Converter = new JavaScriptDateTimeConverter(); @@ -117,7 +120,7 @@ namespace Newtonsoft.Json.Tests.Documentation { string json = JsonConvert.SerializeObject(new DateTime(2000, 10, 10, 10, 10, 10, DateTimeKind.Utc), new JsonSerializerSettings { - ContractResolver = new ConverterContractResolver() + ContractResolver = ConverterContractResolver.Instance }); Console.WriteLine(json); diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj index afa8eb6d..a2083c25 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj @@ -117,6 +117,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index 19683bd3..22046b2c 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -76,5 +76,5 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.10.15427")] +[assembly: AssemblyFileVersion("4.5.10.15431")] #endif diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 715b0c5c..3f86979e 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.10.15427")] +[assembly: AssemblyFileVersion("4.5.10.15431")] #endif [assembly: CLSCompliant(true)]