User Experience Engineering

Thursday, April 14, 2011

 

Mootools intrudes on native JSON and Crockford's json2.js

I recently upgraded an application to use JSON2. When it was used in an environment containing Mootools 1.2.4, the application broke, throwing an error, "failed to deserialized json object". The application is portable, and has to play nicely in polluted waters. The object to be serialized client side had an attribute that was a two-dimensional array, constructed as array literals:
    "foo": [[1, "string", "anotherstring" {object:true}]] 
I expect output like this from JSON.stringify:
    "foo":[[1, \"string\", \"anotherstring\" {object:true}]] 
And I get it, from native JSON, from json2.js, and from the older YAHOO.lang.JSON. Mootools returned:
    "foo":"[[1, \"string\", \"anotherstring\" {object:true}]]"
The object attribute was represented as a string! So, I dug into the reasons why the shiny new JSON2 library had this issue, and only with Mootools present. Here is some history, and results of debugging.
  1. Collisions between Mootools JSON.js and browser-native JSON were tragically ignored by mootools devs in February 2009: https://mootools.lighthouseapp.com/projects/2706/tickets/607-native-json-support-in-firefox-31
  2. Another collision report (November 2009) was closed wontfix after sitting a year: https://mootools.lighthouseapp.com/projects/2706/tickets/796-mootools-jsonencode-vs-json2-jsonorg-jsonstringify
  3. Some effort was made to address issues in Mootools 1.3.1, February 15, 2011: http://mootools-users.660466.n2.nabble.com/Moo-Native-JSON-encoding-and-decoding-td6019259.html
To summarize the thread, Mootools users complained that a) Mootools does not use native JSON when available, and b) Mootools JSON does not support ECMA 5 standard method names "parse" and "stringify". Mootools developers argued that they "MooTools had the JSON object before it was specified" and that they did not like the names "parse" and "stringify". Mootools developers ended up apologizing, but not for the fundamental flaw: that of modifying native JavaScript Objects in the first place. It would seem that my application's issue were solve because Mootools 1.3 has not tacked .toJSON onto the array-like [] object.
    typeof value.toJSON === 'function') { 
       // (JSON2's test now returns false, so the serialization is handled by JSON, not Mootools)
Below is the nitty gritty of how Mootools 1.2.4 can break JSON2. Mootools 1.2.4 Here's the line where Crockford's JSON2.js tries to optimize by using a native method:
    function str(key, holder) {
        ...
// If the value has a toJSON method, call it to obtain a replacement value.

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }
Execution steps into Mootools' intrusive method:
Native.implement([Hash, Array, String, Number], {
 toJSON: function(){
  return JSON.encode(this);
 }
});
Mootools $type function returns 'array' for a literal []. (Standard typeof operator returns 'object')
     obj.$family.name // property $family was added by Mootools 

Comments: Post a Comment

Links to this post:

Create a Link

Archives

March 2006   May 2006   July 2006   August 2006   January 2007   March 2007   April 2007   August 2007   March 2008   April 2008   August 2008   April 2010   May 2010   July 2010   September 2010   April 2011   November 2012   March 2013   December 2013  

This page is powered by Blogger. Isn't yours?