Native JSON Support in IE8 and Tracking the ECMAScript Fifth Edition Draft Specification

UPDATEMicrosoft has released an update that addresses most of the issues discussed below. Refer KB976662 for more information about the update. The MSDN links for JSON documentation - JSON.stringify, JSON.parse and toJSON, have also been updated to reflect these changes.

First, to wait till the new specification is approved so that we can ship a fully compliant native JSON feature. This had a big disadvantage of not being able to provide web developers with both – performance and security benefits that native JSON offers over a script implementation of JSON in IE8 (as final approval of the standard was at least a year away).

Second, providing JSON support in IE8 based upon early drafts of the standard and then, if necessary, bringing the IE JSON support into compliance with the ES5 specification once the standard is ratified (currently expected to happen in Dec’09). This option had the disadvantage that if the specification changed after IE8 shipped there would be a period time during which the IE8 JSON support would have variances from the ES5 specification.

Weighing the two, we decided to choose the second option as it meant providing web developers the ability to start taking advantage of the native JSON constructs immediately. Moreover, the changes that were expected in the specification were not drastic and could easily be detected and worked around as needed by providing simple wrappers created in JScript itself.

Both, the candidate draft of the ES5 Specification and IE8 are now available. The list of differences that currently exist between the implementation and the draft specification is provided below with possible workarounds. It is worth noting that additional changes may still be made to the candidate ES5 specification based upon reviewer feedback. What this means is that the final form factor of JSON might be a bit different than the draft or what is covered in this article by the time ES5 is standardized.

Following is a list of differences between IE8’s behavior and the current ES5 Draft Specification of

If value is undefined and is not replaced using a replacer function, stringify should return undefined instead of the string "undefined".

If valueis a function and is not replaced using a replacer function, stringify should return the value undefined rather than the string "undefined".

If value is a Number or String object after the toJSON() method and replacer function have been executed on value, stringify should return the primitive number or string value stored in the Number or String object. Note: Per the latest ES5 errata (27 May’09) Boolean objects are also included in this.

If value is a cyclic object or array, stringify should throw a TypeError and not an Error.

If replacer is not a Function or an Array, stringify should ignore the replacer parameter and not throw an error.

If the replacer function calls a DOM method and passes the key parameter to the same, stringify should not throw an Error. Note: To work around this issue, use key.toString() when passing key to DOM methods like alert() and createElement() inside the replacer function.

If space is an empty string, stringify should default space to an empty string instead of newline.

If space is a Number object or a String object, stringify should use the primitive value of the objects instead of ignoring the same.

If space is set to a value greater than 100, stringify should default space to be 100 instead of the current maximum limit of 65535 after which space is defaulted to 0. Note: Per the latest ES5 errata (27 May’09) the max space should be defaulted to 10.

If space is a non integer numeric value, stringify should default space to be the integer part of the space value instead of defaulting it to the ceiling value of the space argument.

If text contains control characters other than TAB, CR, or LF, throw a Syntax Error. In addition, throw a SyntaxError if TAB, CR, or LF appear in a JSON string literal. IE8 correctly rejects illegal characters outside of string literals. Note: To work around this problem for string literals, user can define a reviver method that looks for string values containing control characters. Given the performance tradeoff to find these characters in all JSON text strings, a generic reviver is not provided in the sample below.

Note that the majority of these differences concerning the handling of invalid argument values or other unusual situations. Most of them have no impact on the encoding or decoding of normal data.

A workaround for these differences is provided in the following patchJSON function which can be called to suitably modify the built-in JSON support methods, before using any of the JSON built-ins by a user. It places a wrapper around the built-in JSON functions.

Because the above patch primarily deals with errors that arise from improperly calling the JSON functions it is most useful while you are debugging your code. When you code is ready for production you may not need to use.

Note: Apart from the above differences due to the changes in the ES5 draft specifications for JSON, there is a known issue which currently exists for IE8. The details of the same along with the possible workarounds are covered in this blog post.

In case you will like to follow the discussions by the TC39 members around how the standard is taking shape, and the discussion around the changes for JSON, you can refer the discussion archives here. The latest ES5 drafts are available at the ECMAScript wiki.