Fastest JSON Serializer for .NET released

August 17th, 2010 by mythz Leave a reply »

New! Benchmarks graphs are now available to better visualize the performance of ServiceStack’s JSON and JSV text serializers.

Due to my unhealthy obsession for producing software that runs fast, I’m releasing a shiny new JSON Serializer for .NET into the wild!

ServiceStack JsonSerializer is based upon my previous efforts of inventing a fast, new compact text serializer with `TypeSerializer`
and its JSV Format. Essentially I just refactored the current JSV code-base to support multiple serializers and then simply added an
adapter for the JSON format. Unfortunately in my quest of adding a JSON serializer to the feature list I’ve given up a little perf in the JSV TypeSerializer by
not being able to apply more aggressive static-type optimizations and method in-lining.  However I ended up preferring this option rather than having to branch the existing code-base to support
two fairly large almost identical code-bases doubling my efforts whenever I want to add new features or fix a bug. Although the good news is that the library is still Reflection.Emit code-free
so future optimizations are still possible!

Anyway based on the latest Northwind database benchmarks perf didn’t suffer too much
as JSV is still the fastest text serializer for .NET with the newly released JSON serializer not too far behind :)
The benchmarks is showing the new JSON Serializer now over 3.6x faster than the BCL
JsonDataContractSerializer and is around 3x faster than NewtonSoft JSON.NET (the previous fastest JSON serializer benchmarked).
(Other popular JSON serializers LitJSON and JayRock were also benchmarked although both were found to be slower and more buggier than the previous options).

It also happens to be 2.6x faster and 2.6x more compact than the fastest Type serializer in the BCL – Microsoft’s Xml DataContractSerializer, giving yet another
reason for JSON lovers to prefer it over XML.

Serializer Payload size Larger than best Avg Slower than best
Microsoft DataContractSerializer 4097 4.68x 838.1957 6.93x
Microsoft JsonDataContractSerializer 1958 2.24x 1125.8554 9.31x
Microsoft BinaryFormatter 4927 5.62x 1113.4011 9.21x
NewtonSoft.Json 2014 2.30x 947.2970 7.83x
ProtoBuf.net 876 1x 120.9475 1x
ServiceStack TypeSerializer 1549 1.77x 270.0429 2.23x
ServiceStack JsonSerializer 1831 2.09x 312.6265 2.58x

(Combined results based on the Northwind database benchmarks. Payload size in bytes / Times in milliseconds)

Features and Usages
Effectively the JSON serializer is optimized for one task which is to Serialize/Deserialize types fast. Where possible I try to remain compatible with the BCL’s JsonDataContractSerializer by for example choosing to serialize DateTime using the WCF JSON format (i.e. /Date(1234+0000)/).

Although that being said the serializer tries to serialize as much as possible while at the same time being non-invasive and configuration free:

  • Serializes / De-serializes any .NET data type (by convention)
    • Supports custom, compact serialization of structs by overriding ToString() and static T Parse(string) methods
    • Can serialize inherited, interface, anonymous types or ‘late-bound objects’ data types
    • Respects opt-in DataMember custom serialization for DataContract dto types.

Developers wanting more features like outputting ‘indented JSON’ or building a dynamic JSON structure with LINQ 2 JSON would still be better off with the popular NewtonSoft JSON.NET.

In keeping with tradition I’ve retained a simple API:

string JsonSerializer.SerializeToString<T>(T value);
void JsonSerializer.SerializeToWriter<T>(T value, TextWriter writer);
void JsonSerializer.SerializeToStream<T>(T value, Stream stream);
T JsonSerializer.DeserializeFromString<T>(string value);
T JsonSerializer.DeserializeFromReader<T>(TextReader reader);
T JsonSerializer.DeserializeFromStream<T>(Stream stream);

Basic Usage Example

var customer = new Customer { Name="Joe Bloggs", Age=31 };
var json = JsonSerializer.SerializeToString(customer);
var fromJson = JsonSerializer.DeserializeFromString<Customer>(json);

Reasons for yet another .NET JSON Serializer

I only recently decided to develop a JSON serializer as I was pretty happy with my JSV format in fulfilling its purpose quite well by providing a fast, human readable, version-able, clean text-format ideal for .NET to .NET web services or for serializing any text blob (e.g. in an RDBMS or Redis, etc).

Unfortunately I recently hit a few issues which called for the use of JSON over JSV:

Ajax Benchmarks

The benchmarks after porting the JSV format over to JavaScript (to be able to use it inside Ajax apps) on the upside showed that it was actually a little quicker to deserialize than ‘safe JavaScript’ in advanced browsers (read: any browser NOT Internet Explorer). On the downside Native evaluation of ‘unsafe JavaScript’ was still quicker in those browsers. Unfortunately the biggest problem was performance in Internet Explorer sucked in comparison as at times was over 20x slower compared to its own eval. Now I’ve long ago become a silent proponent of the ‘Death to IE6′ group by electing not to test/support it, unfortunately given its significant market share I really couldn’t do the same for IE7 and IE8 so for overall performance reasons using the existing BCL JSON serializer was still the way to go.

Embracing the future Web (Ajax / HTML5)

It appears that dynamic web applications using Ajax and HTML5 are quickly becoming the first-choice platform for developing advanced client UI applications. I believe that pure ajax applications (i.e. static html/js/css talking directly to JSON data web services) will quickly supersed rich plugin frameworks like Flash and Silverlight with the help of sophisticated JavaScript frameworks like jQuery, the Google Closure Library and the upcoming browsers broad support for HTML5. I consider performance to be one of the most important features for an application so having a fast JSON Serializer would increase ServiceStack’s appeal as a high-performance Ajax server to power these new breed of apps.

Redis Interoperability

Although Redis potentially supports storing any binary data, it does have first class support for UTF8 strings. There have started to be some talk in the redis mailing groups for client library maintainers to choose to standardize on storing text blobs using JSON for simplicity and interoperability reasons. At the moment ServiceStack’s C# Redis Client is currently using the JSV format to store complex types because of its inherent perf and versionability characteristics, however this is likely to change to use JSON in a future release.

JSON support in Mono

Unfortunately over the years Mono’s implementation of the BCL’s JsonDataContract hasn’t improved much and is still the number 1 reason why some ServiceStack examples don’t work in Mono. This ended up being the motivating factor as I recently added preliminary REST support in ServiceStack (details in a future post) and was not able to run the live examples since I only have access to a Linux web host (thus requiring mono).

In the end, I decided to bite the bullet and jump on the NIH bandwagon again and develop a JSON serializer which would ultimately yield a few benefits mainly by making the ServiceStack web framework a very fast .NET Ajax/JSON server and hopefully positioning it as the preferred platform for developing high-performance cross-platform web services.

Now the default Json Serializer in ServiceStack

I’ve refactored all the ServiceStack.Text.Tests to support and test both the JSON and JSV formats and added a fair few JSON-specific tests as well – so even though its new I consider the new JsonSerializer to fairly stable and bug-free so much so that I’ve made it the default Json serializer in ServiceStack. As a result all my live ServiceStack examples are now working flawlessly on Mono!

If new serializer is causing some problems for existing ServiceStack users please file any issues you have or alternatively you can revert back to using the .NET’s default JsonDataContractSerializer by setting the global config option in your AppHost, i.e.

SetConfig(new EndpointHostConfig { UseBclJsonSerializers = true});

Download JsonSerializer

JsonSerializer is available in the ServiceStack.Text namespace which like the rest of Service Stack it is released under the liberal Open Source New BSD Licence which you can get:

NewtonSoft
Advertisement

15 comments

  1. Craig says:

    I just ran my own tests using XmlSerializer, JavascriptSerializer, DatacontractSerializer and JsonSerializer and your serializer came 2nd best to Javascriptserializer in serializing an array of simple types (guid,string) to json strings on vista business .net c# 2008 in a console app running in release using stopwatch (with resets) and running about 100 iterations.

    • mythz says:

      Hi Craig,

      That’s because there is a one-time penalty for creating and caching all the delegates to make subsequent calls fast. Try your benchmark again skipping the first call.
      Serializers like the JsonSerializer are optimized to be used in long-running applications like web servers so its best to optimize accordingly.

  2. MGholam says:

    Please can you implement the following:
    1.ability to serialize and deserialize a list of derived objects
    e.g.
    List items;
    items.add(new class1()); // class1:baseclass
    items.add(new class2()); // class2:baseclass

  3. Mark says:

    Hi Demis

    First of all, great library, I use it a lot and it has served me well. I just came across one problem that I’m not sure is a documented shortcoming or if I am just doing it wrong? It seems the deserialization of json data does not cater for collections? I created an object with a parent-child relationship and tried to run it through deserialization ( after serializing the object with the same library ) and it only deserializes the root object, no children? The DataContractJsonSerializer does however deserialize it correctly. Any thoughts?

    here is the test code…

    List branches = new List();
    branches.Add(new JSTreeItem { name = “child1″ });
    branches.Add(new JSTreeItem { name = “child2″ });
    branches.Add(new JSTreeItem { name = “child3″ });

    var tree = new JSTreeItem { children = branches, name = “root” };

    var json = JsonSerializer.SerializeToString(tree);
    var fromJson = JsonSerializer.DeserializeFromString(json);

  4. dave says:

    Have you seen Mehdi Gholam’s fastJSON implementation on codeproject? I think his is a little more versatile in what it will serialize and deserialize but he claims faster performance than yours:

    http://www.codeproject.com/KB/IP/fastJSON.aspx

    I think the general idea and approach is the same as yours, create some cached dynamic methods to burn through objects…

  5. Henry Nguyen says:

    Can this serializer be supported in .NET Compact framework?

  6. Carol says:

    Thanks for the great library. I’m looking forward to implementing it (and getting rid of the DataContractSerializer!) in my CouchDB client.

Leave a Reply