Here's a (not so brief) explanation on the recent changes and the
upcoming plans for our JSON API.

Our previous JSON implementation was based on Douglas Crockford's
original proposal in which primitives, Array and Object prototypes
each had their own toJSONString method. We mimicked that behaviour
with two exceptions: 1) we did not extend Object.prototype and 2) we
called our methods toJSON instead of toJSONString because our API was
slightly different (Crockford's implementation took an extra arguments
for prettifying the output string; ours didn't), and because we wanted
to avoid naming collisions.

Unfortunately, the specification was modified a number of times until
it was stabilized in ES5's final draft not long ago.

First of all, the toJSONString method was dropped in favor of a toJSON
method (hello naming collision).

Secondly, all but Date.prototype.toJSON methods where dropped.

Finally, where the toJSONString method returned… a string, the new
toJSON method now returned a native object or primitive ready to be
stringified:

    new Date().toJSONSting();
    // -> "\"2010-02-26T16:23:40Z\""

    new Date().toJSON();
    // -> "2010-02-26T16:23:40Z"

Notice how the first example returns a quoted string while the return
value of the second one isn't quoted.

Our JSON implementation had the method names of the ES5
implementations with the behaviour of the original JSON spec. That
obviously caused a lot of issues with services which relied on the
native JSON object when present, hence the decision to modify this
behaviour for our next release (1.7).

String.prototype.evalJSON behaves like JSON.parse except:

a) it does not accept a reviver,
b) it internally calls String.prototype.unfilterJSON to help protect
against JavaScript Hijacking[1].

Whenever the native JSON object is present _and works correctly_
String.prototype.evalJSON acts as a wrapper around it. Whenever the
native JSON object isn't present (or is broken), we provide our own
implementation. In which case the JSON-formatted string is not parsed
but evaled, but can be sanitized using JSON2's regexp tests by setting
the sanitize flag to true.

Object.toJSON behaves like JSON.stringify except:

a) it doesn't accept replacer and space arguments, and
b) Object.toJSON(Object) will yield undefined instead of {} (not that
this seems like such a big deal).

Again, whenever the native JSON object is present and works properly
our implementation just acts like a wrapper around it.

The reason for not providing the JSON object when it's missing is
threefold:

1. For now, we don't judge the reviver, replacer and prettifier
options necessary. Providing our own API allows us to avoid
implementing those for the time being.
2. Some browsers' JSON implementations are broken. If we weren't
relying on a wrapper, we'd be forced to replace these altogether.
3. The native API is made of static methods, so being forced to use a
wrapper API has a lot less impact on code readability than when
"instance" methods are missing. Compare:

    JSON.stringify(foo);
    // and
    namespace.JSON.stringify(foo);

with

    [1, 2, 3].map(function(e) { return i++; }).join(', ');
    // and
    namespace.map([1, 2, 3], function(e) { return i++; }).join(', ');


I can imagine that our JSON implementation in Prototype 2.0 will match
the native API more closely but will stay in it's own namespace (as in
the example above).

Hope this clarifies the recent changes.

Best,

Tobie

1. 
http://www.fortifysoftware.com/servlet/downloads/public/JavaScript_Hijacking.pdf

-- 
You received this message because you are subscribed to the Google Groups 
"Prototype: Core" group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en

Reply via email to