Find file
420468f Aug 17, 2014
108 lines (71 sloc) 8.63 KB

Fastest JSON Serializer for .NET released

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
Microsoft JsonDataContractSerializer 1958 2.24x 1125.8554
Microsoft BinaryFormatter 4927 5.62x 1113.4011
NewtonSoft.Json 2014 2.30x 947.2970 876 1x 120.9475
ServiceStack TypeSerializer 1549 1.77x 270.0429
ServiceStack JsonSerializer 1831 2.09x 312.6265

(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 HostConfig { 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:

Included as part of the Service Stack binaries – ServiceStack/downloads Available as a standalone dll – ServiceStack.Text/downloads