Comments to the JSON related proposals

Simon Bünzli zeniko at gmail.com
Sat Aug 18 16:39:13 PDT 2007


Brendan asked me to comment on the proposals at [1] after having seen 
that I had implemented several aspects slightly differently for Firefox' 
Session Restore functionality (which offers a JSON-based API [2]). This 
implementation in JavaScript is planned to be used for the Mozilla 
platform until the JSON proposal is finalized and natively implemented [3].

JSON was a nice fit for our API as we internally use an object tree to 
store the various information related to all open windows. For 
efficiency and simplicity reasons, we do however store certain 
non-serializable objects in that tree as well which required us to 
implement a filter on toJSONString (see comments #1 and #2 below).

With the code being added to the Mozilla platform, I made some 
additional changes to make it IMO slightly less fragile to use - that's 
comments #3 and #4. The other two comments #5 and #6 are unrelated 
suggestions which we haven't implemented ourselves yet.

My 6 modification suggestions are:

1. toJSONString needs an optional filter argument

This has already been discussed but apparently not made it into the 
proposal itself. To reiterate the main reason: without a filter, an 
object containing temporary/internal keys has to be duplicated first 
before it can be encoded - and duplicating it or JSON encoding it 
yourself will of about the same complexity, so you lose the convenience 
of either being able to add internal keys or of using toJSONString.

2. The optional filter argument should allow both function and blacklist

This shouldn't be an either/or choice, as there are several use cases 
where a filter might be used which have quite different needs: in the 
case of temporary/internal keys scattered in an object, it might be 
easier to just specify those keys and be done with it - whereas if you 
want to ensure a contract (and thus prefer a whitelist), you'll need a 
way to consider a key's context which you can only do in a function 
anyway (unless you want to introduce XPath4JSON).

In the first case you furthermore most probably use less temporary keys 
than actually relevant ones which makes the blacklist both 
smaller/better to oversee and speedier than a whitelist.

3. |undefined|, functions, etc. should not be silently dropped

Since JSON is a serialization format, encoding and decoding should be 
fully reversible - or else you risk running into unexpected subtle 
errors which make JSON related code more fragile than necessary.

Should objects to be serialized for some reason contain functions, they 
should rather be blacklisted so that it is explicit what will be dropped.

|undefined| OTOH mostly appears in sparse Arrays which don't exist in 
many other languages and which you thus shouldn't be using for 
interoperability's sake, anyway. If you however depend on sparse Arrays 
(i.e. if you couldn't for clarity rewrite your code to use dense 
Arrays), you again risk subtle errors if you're not aware that you won't 
get them back as you might expect.

Only possible exception to this rule: dropping |undefined| at the very 
end of an Array for the use case where you preallocate an Array larger 
than you need for efficiency reasons.

4. Date should not be serializable

Same reason as above: as long as it's not unambiguously deserializable, 
serializing it leads to unnecessary fragility. Having instead a filter 
function on toJSONString analogous to parseJSON's would nicely restore 
the balance for easy-to-read encoding/decoding.

5. Pretty printing shouldn't default to 4 spaces

Indentation is always a matter of taste and should thus not default 
unchangeably to an arbitrary value. Two better options: either indent 
with a single tab (which can then easily be replaced with as many spaces 
as you like as there won't be any other unencoded tabs in the returned 
string); or accept an integer value as argument indicating how to indent 
where non-negative numbers mean spaces and negative numbers mean to use 
as many tabs for indentation.

6. Filter functions should be able to delete keys by returning |undefined|

|undefined| is an illegal JSON value and can thus be used safely for 
this purpose, allowing you to do completely without Array.filter or 
similar both for encoding and decoding. This would mostly be used for 
encoding where with a filter function you can choose yourself to 
implement a whitelist (or an extended blacklist).

----

Criticism and comments are welcome. In case any of those arguments has 
already been brought forward, please kindly ignore them.

~sb

[1] 
http://wiki.ecmascript.org/doku.php?id=proposals:json_encoding_and_decoding
[2] http://developer.mozilla.org/en/docs/nsISessionStore
[3] https://bugzilla.mozilla.org/show_bug.cgi?id=386789




More information about the Es4-discuss mailing list