Json.NET 3.5 Release 7 – Biggest Release Ever Edition

Improved BSON Performance

BSON performance has improved markedly in R7. Deserializing is as fast as it was before (i.e. ridiculously fast) but writing BSON has gotten a big boost when writing large complex objects. Using an extreme example this benchmark compares the previous release with the new BSON serializer:

All right, all right, you win. Heh. I see you've played knifey-spooney before.

ShouldSerialize

Did you know that the good old XmlSerializer had support for conditionally deciding what to serialize through ShouldSerialize methods? Me neither.

Not to be outdone, Json.NET is now able to dynamically include and exclude properties the same way. Add a boolean method with the same name as a property and then prefixed the method name with ShouldSerialize. The result of the method determines whether the property is serialized.

In the example below possible circular references are manually handled by testing whether an employee is its own manager before serializing:

public class Employee
{
  public string Name { get; set; }
  public Employee Manager { get; set; }
 
  public bool ShouldSerializeManager()
  {
    return (Manager != this);
  }
}
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"
//   }
// ]

Build Scripts

Oh, it's no use. I'm never going to find that tree. This whole raid was as useless as that yellow, lemon-shaped rock over there. Wait a minute...there's a lemon behind that rock!Now include with the Json.NET source code are the build scripts used to compile and package Json.NET. A couple of months ago I switched from a clunky old batch script I had been using to Powershell and psake. Compared to past solutions I’ve written using NAnt I’m very happy with the results. XML be gone!

And More

As always there are a crazy number of major (ISerializable support, LINQ to XML XmlConverter support) and minor new features (support for reading octal and hexadecimal numbers from JSON, numerous improvements to the serializer).

Json.NET Release 7 has the biggest change list yet – in fact I had to edit the descriptions of the changes down to fit them all in CodePlex’s release notes size limit!

Changes

Here is a complete list of what has changed since Json.NET 3.5 Release 6.

 

  • New feature - Improved BSON performance
  • New feature - Added WriteOid and WriteRegex to BsonWriter
  • New feature - Added support for ShouldSerialize conditional methods
  • New feature - Added TypeNameHandling to JsonProperty attribute. Allows a type names to be included on an individual property basis
  • New feature - Support for reading octal and hexadecimal numbers from JSON
  • New feature - Added support for enum values to LINQ to JSON
  • New feature - Added TypeNameAssemblyFormat property to JsonSerializer
  • New feature - Added DateTimeConverterBase
  • New feature - Added JsonPrimitiveContract and JsonLinqContract
  • New feature - Added CreateMemberValueProvider method to DefaultContractResolver
  • New feature - INotifyCollectionChanged implemented on JContainer in Silverlight
  • New feature - Included BSON in .NET 2.0, Silverlight and Compact Framework builds
  • New feature - Added ReadRootValueAsArray, DateTimeKindHandling properties to BsonReader
  • New feature - ISerializable support
  • New feature - Added GetSchema, CanRead, CanWrite to JsonConverter
  • New feature - LINQ to XML support added to XmlNodeConverter
  • New feature - SerializeXNode, DeserializeXNode methods added to JsonConvert
  • New feature - Added support for sharing a static cache for contract resolvers inheriting from DefaultControlResolver
  • New feature - Added support for switching between dynamic and late bound reflection for medium trust environments
  • New feature - Support for using implicit/explicit casts when converting a JSON property name to a dictionary value
  • Change – JsonConverter.ReadJson method is now passed the existing value of the property it is converting
  • Change - Built in JsonConverters are resolved once when the contract is created rather than runtime
  • Change - JsonRaw removed and replaced with JRaw
  • Change - Type is now always written as AssemblyQualifiedName
  • Change - Dictionary key serialization falls back to ToString for keys
  • Change - Schema generator now uses JsonContracts to determine schema information
  • Change - Removed the "-" prefix when serializing a JSON constructor - prefix not compatible with XML naming standard
  • Change - When converting JSON to XML using XmlNodeConverter, changed special JSON properties ($id, $ref, $type) to be attributes rather than child elements
  • Fix - Fix dynamic code generation IL verification issues in .NET 4
  • Fix - Fix error when deserializing nullable array
  • Fix - Escape JSON property text
  • Fix - Silverlight serialization security error
  • Fix - Private base members marked with JsonProperty attribute now correctly serialized
  • Fix - Error message when attempting to deserialize custom dictionary with no default constructor
  • Fix - Correctly deserialize empty BSON objects
  • Fix - When a class has a metadata class defined, fall back the original class from the metadata class when attribute not found
  • Fix - Deserialize HashSet<T> without error
  • Fix - Correctly skip ignored JSON properties when deserializing via a non-default constructor
  • Fix - Schema with no properties now correctly validates
  • Fix - Dictionary and array schemas now marked as nullable
  • Fix - Serialize generic dictionary that doesn't implement IDictionary correctly
  • Fix - CustomCreationConverter no longer errors when writing JSON
  • Fix - JsonProperty.Readable and Writable not being correctly set for .NET properties with modified getter/setter visibility
  • Fix - Fix error caused by private properties on a base class when reflecting a type
  • Fix - Correct property CanRead and CanWrite coming back as false when a base class property has a private getter/setter visibility
  • Fix - Fix reading BSON multi byte UTF8 characters
  • Fix - CustomCreationConverter to return null when converting a null JSON value
  • Fix - Fix for possible errors caused by mutable GetHashCode implementations and reference tracking
  • Fix - Fix JTokenReader.ReadAsBytes to read strings as base64 data

Links

Json.NET CodePlex Project

Json.NET 3.5 Release 7 Download – Json.NET source code, documentation and binaries

Sunday Podcasts 4

Son. If you really want something in this life, you have to work for it. Quiet! They're gonna announce the lottery numbers. Penny Arcade TVPing Pong 1/Ping Pong 2

The guys at Penny Arcade have branched out from podcasts to a web TV show with predictably hilarious results.

There are a lot of good episodes (PA’s crazy hire process!) but I really love this duo covering Penny Arcade’s obsession with Ping Pong and a rematch game against Bungie, the makers of my beloved Halo.

Smack talk, slow-mo ping pong action shots and an agonist sporting a sinister English accent – what’s not to like?

Now let's all get drunk and play ping pong!

NPR: Planet Money PodcastWe Bought A Toxic Asset!

I wouldn’t call Planet Money a pure economics podcast – it definitely has a bit of an opinion about some economic social issues so viewer discretion is advised – but that doesn’t mean it isn’t interesting.

This episode the people at Planet Money buy a toxic asset and explain in simple language what a toxic asset is and why and how you would buy one. It is a lot more entertaining than I ever would have thought possible.

Oh and bonus points for playing both The Gambler and Danger Zone in a single podcast!

Json.NET Performance With Binary Data

Binary data and text file formats (JSON, XML) don’t tend get along. To be included in JSON or XML binary data has to be encode into a text friendly format, generally base64, which creates overhead both in the time spent encoding/decoding binary, and the extra size of the text encoded data in the message.

{
  "binary": "SGVsbG8gV29ybGQ="
}

The Test

In our test we’ll compare serializing a message with binary data using common .NET serialization methods and compare the result. First our message…

public class Image
{
  public string FileName { get; set; }
  public string Author { get; set; }
  public string Caption { get; set; }
  public byte[] Data { get; set; }
}

And some test data…

This is Fuzzy Bunny. About a year ago he noticed his voice was changing, he had terrible acne, and had fur where there was no fur before.

FileName: bunny_pancake.jpg Author: Hironori Akutagawa Caption: I have no idea what you are talking about so here’s a bunny with a pancake on its head.

The Results

Json.NET and the DataContractSerializer are about equal to each other in the size of the resulting message – each is encoding the image byte array as base64 encoded text. The small edge to Json.NET comes from the smaller size of the JSON metadata compared to the DataContractSerializer’s XML.

Json.NET BSON and the BinaryFormatter are binary formats so they can include the image data directly in the message. They’re approximately 25% smaller than JSON/XML by saving the overhead of base64. Again the Json.NET BSON format is more efficient than the BinaryFormatter making it slightly smaller.

Finally as you can see the WCF DataContractJsonSerializer is by far the least efficient. When I looked into why it performed so badly it turns out that the WCF JsonSerializer serializes binary data as a JSON array of integers, one integer representing each byte. It goes without saying that you should never use the WCF JsonSerializer with binary data.

Lisa, if the Bible has taught us nothing else - and it hasn't - it's that girls should stick to girls' sports, such as hot-oil wrestling, foxy boxing, and such-and-such.

kick it on DotNetKicks.com