Extension Developers – Native JSON Parsing

Firefox 3 is using JSON to store data in several places – such as bookmark backups, session restore, and offline manifests. Originally, JSON parsing was scattered through the code. Then it was consolidated to JSON.jsm, a JavaScript code module. Eventually, it was converted into nsIJSON.idl, a C++ XPCOM Component. What does this mean to extension and application developers? Well, you now have access to JSON encoding and decoding routines that can be a lot faster (more in a bit) than the JavaScript counterparts.

var testObj - { name: "Jimmy", age: 25, loves: ["XULRunner", "sunrises", "Mt Dew"] };

// encode to string using javascript implementation
Components.utils.import("resource://gre/modules/json.jsm");
var testJS = JSON.toString(testObj);

// encode to string using native implementation
var Ci = Components.interfaces;
var Cc = Components.classes;

var nativeJSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
var testNative = nativeJSON.encode(testObj);

Of course, you can also encode to a string using the json2.js code at json.org

I put together a little benchmark (on bug 410890) to get a feel for the speed improvements that could be obtained using native JSON parsing. The code iterates over a fixed chunk of JSON (taken from Robert Sayre’s unit tests) multiple times. The number of iterations are on the x-axis while the milliseconds required are on the y-axis:

Encoding
json-object-encode.png

Decoding
json-object-decode.png

I found that John Resig did some JSON benchmarking last year, so I made a second benchmark script (same bug) that used his 1600 item array as the JSON source. This code takes the 1600 item array and breaks it into variable sized chunks, then sends those different sized chunks into the JSON parsers. The chunk size is on the x-axis while the milliseconds required are on the y-axis:

Encoding
json-array-encode.png

Decoding
json-array-decode.png

The tests show a very nice performance improvement for encoding JavaScript objects to JSON data. The performance improvements for decoding JSON data into JavaScript objects is smaller, but still very worthwhile. For the curious, the original native JSON code was further optimized to increase the improvements.

Note: Currently, native JSON is only available to privileged code with access to XPCOM. This means that web content JavaScript is not yet able to access the feature. Working is moving ahead in this bug to get these APIs exposed to web content as well. Exposing APIs to web content is something that needs to be thought out and perhaps standardized. There was a proposal to add JSON encoding/decoding to ES4, which seems to have been dropped. Maybe the WHAT WG will draft something.

Check out John Resig’s post on the State of JSON for lots more information on JSON, web content and standards.

2 Comments

  1. Mukunda Modell said,

    February 18, 2008 @ 12:29 am

    I can’t seem to get this to work in a recent XULRunner nightly – is this a firefox-only feature?

  2. Mukunda Modell said,

    February 18, 2008 @ 2:24 am

    Figured it out: filenames are case sensitive on Linux and the file is JSON.jsm so the code above should read:

    Components.utils.import(“resource://gre/modules/JSON.jsm”);

RSS feed for comments on this post