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 _______________________________________________ Es4-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es4-discuss
