Freigeben über


Native JSON in IE8

As you may have guessed from the title of this post, Internet Explorer 8, as of Beta 2, offers native JSON parsing and serialization. This new native JSON functionality enables Internet Explorer 8 aware AJAX applications to run both faster and safer!

What’s JSON?

For those of you that are not die hard AJAX developers, allow me to provide a bit of background. JSON is a simple human readable data interchange format often used by AJAX applications when transmitting data between the server and the web application.

For example, imagine that you select a contact name from your favorite web mail client so that you can see the contact information. The server might send down a stream of data to the web application (which is running in the browser) that looks like this:

     {
"firstName": "cyra",
"lastName": "richardson",
"address": {
"streetAddress": "1 Microsoft way",
"city": "Redmond",
"state": "WA",
"postalCode": 98052
},

           "phoneNumbers": [
"425-777-7777",
                 "206-777-7777"
           ]
}

Fortunately, this format is syntactically compatible with Javascript. Many applications today will use the Javascript eval() function to convert the data payload into a Javascript object. Using eval() is a dangerous and expensive approach. eval() parses the string as a general Jscript expression and executes it. If the string being passed to eval() has been tampered with, it could contain unexpected data or even someone else’s code – which is now injected into your web application.

There are libraries, written in Javascript, that are designed to more safely parse untrusted JSON payloads. Some libraries do a strict verification of the data payload using a parser written in Jscript (https://www.json.org/json_parser.js). Some libraries, like json2.js, do a sanity check on the input string using a regular expression then use the faster eval() for parsing . The ideal solution is a native implementation that protects the application from code injection, is fast and available everywhere.

Native JSON in IE8 Jscript

The Jscript engine for IE8 now has a full native implementation of JSON that significantly improves the speed of serialization, deserialization and improves the overall safety of parsing untrusted payloads while maintaining compliance with JSON support as described in ES3.1 Proposal Working Draft

APIs

We defined a new built-in object ‘JSON’. The object can be modified or overridden. It looks like math or any other intrinsic global object. In addition to the JSON object, special functions, toJSON() , are added to the prototypes of Date, Number, String, boolean objects. The JSON object has two functions: parse() and stringify() .

Example:

var jsObjString = "{\"memberNull\" : null, \"memberNum\" : 3, \"memberStr\" : \"StringJSON\", \"memberBool\" : true , \"memberObj\" : { \"mnum\" : 1, \"mbool\" : false}, \"memberX\" : {}, \"memberArray\" : [33, \"StringTst\",null,{}]";
var jsObjStringParsed = JSON.parse(jsObjString);
var jsObjStringBack = JSON.stringify(jsObjStringParsed);

The object produced by the parse() method and serialized back by stringify() method is the same as:

var jsObjStringParsed =
{
"memberNull" : null,
"memberNum" : 3,
"memberStr" : "StringJSON",
"memberBool" : true ,
"memberObj" :
{
"mnum" : 1,
"mbool" : false
},
"memberX" : {},
"memberArray" :
[
33,
"StringTst",
null,
{}
]
};

JSON.parse(source, reviver)

The JSON.parse method does the the deserialization. It takes the string in JSON format (specified by the argument source) and produces a JScript object or array.

The optional revive argument is a user defined function used for post parse changes. The resulting object or array is traversed recursively, the reviver function is applied to every member. Each member value is replaced with the value returned by the reviver. If the reviver returns null, the object member is deleted. The traversal and the call on reviver are done in postorder. That’s right; every object is ‘revived´ after all its members are ‘revived”.

The reviver is mainly used to recognize the ISO like strings and transform them in Date objects. As of today, JSON format is not round tripping in Date objects because there is no JScript standard Date literal. ES3.1 draft contains an example of how to make up for this issue using a reviver function.

JSON.stringify(value, replacer, space)

This is the serialization method. It takes the object or the array specified by the value argument and produces a string in JSON format. The value object or array is visited recursively and serialized as specified by the JSON format . If value has a method ‘toJSON()’ then this method acts as a first filter. The original value is replaced by value.toJSON(key) and the resulted value is serialized. The argument key is a string. It is the member name, key, when a object member like (key : value) is serialized. For the root object the key is the empty string.

Date.prototype.toJSON() produces a clean string with no characters to escape. It acts as the de facto serializer because stringify() would return the original string unchanged. Date objects are serialized via toJSON() method.

Number.prototype.toJSON() , String.prototype.toJSON() , Boolean.prototype.toJSON() functions return the ValueOf(). They are intended for correct serialization of objects like “ var num = new Number(3.14);”

The optional replacer argument acts as a filter and it is applied recursively. It could be a function or an array.If the replacer is a function then replacer(key,value) is invoked for each object member key:value . For the root object we call replacer(“”,value) . If the replacer is an array, it must be an array of strings. The elements of the array are the names of the members selected for serialization. The order of serialization is the order of the names in the array. An array replacer is ignored when serializing an array.

The optional space argument is about how to format the output text. If it is omitted, the text will be packed without extra whitespace. If it is a number, it specifies the number of spaces to indent at each level. If it is a string (such as '\t' or ' '), it contains the characters used to indent at each level.

How does this affect existing pages?

The ES3.1 proposal for JSON is the form factor used by the popular json2.js. Well, we take over the name JSON. The global JSON object can be overridden. Still, it is not an undefined object anymore. It is the same with introducing new keywords in a language; taking over a name would eventually affect some existing code. The pages that make use of json2.js are unlikely to be affected. With very few exceptions, all these pages will continue to work, only faster.

The pages that define their private implementation of the JSON object could be affected, especially when the private implementation of JSON object is defined by a pattern like “if(!this.JSON) { JSON=…}”. There are two main options to work around this kind of issues:

1. Migrate existing code to use native JSON support

If the private JSON implementation is based on some of version of json2.js the migration should be very simple.

2. Opt out of the native JSON support and continue to use the existing private JSON object

This can be done by renaming or overriding the JSON name. Renaming means to change over all code using the ‘JSON’ name into some different name like ‘MyJSON’. Overriding means to ensure the private JSON definition overrides all code using the native default JSON definition. In most of the cases, just removing the condition “if(!this.JSON)” should do the trick.

Considering the standardization effort in 3.1, using the name ‘JSON’ Is consistent with our desire to be interoperable through well defined interfaces.

There is a lot more about to talk about the native JSON. The parser is not eval() based, it is a standalone implementation. It is the native equivalent of the reference parser provided at JSON support. It is as safe as (https://www.json.org/json_parser.js ) and it is a lot faster. So if you are using eval() or even your own JSON library, consider checking for the native implementation in IE8 to get increased performance and safer operation.

Corneliu Barsan
Senior Developer
JScript team

Comments

  • Anonymous
    September 10, 2008
    PingBack from http://www.easycoded.com/native-json-in-ie8/

  • Anonymous
    September 10, 2008
    All very cool, but what happens when "naughty" JSON is encountered? Is an empty object returned? An error object returned? null returned? Is the "offending" bit removed? As a developer, if something went wrong, I want to know about it.  How do I find out what didn't work? or do I?

  • Anonymous
    September 10, 2008
    Does this interface also require UTF8 encoded input as per RFC4627 (which is a silly requirement imo)?

  • Anonymous
    September 10, 2008
    > If the reviver returns null, the object member is deleted. You mean undefined, correct?  The latest spec says "If it returns undefined then the member is deleted from the result."

  • Anonymous
    September 10, 2008
    Very Nice! Obviousely, the Native JSON will make things run much more quickly! as Oliver (http://blogs.msdn.com/ie/archive/2008/09/09/what-s-new-for-jscript-for-ie8-beta-2.aspx#8939732) expect. & Hope IE 8 can be more safe on every progress he make!

  • Anonymous
    September 10, 2008
    I love AJAX. I think that what Microsoft has done is very useful. Just must be tested and to re-write the source code.

  • Anonymous
    September 10, 2008
    The comment has been removed

  • Anonymous
    September 11, 2008
    Uno dei post che ho letto con più interesse sul blog del team di prodotto riguarda il supporto nativo

  • Anonymous
    September 11, 2008
    What the !@#$! .stringify();??? Was JSON.serialize(JSONObj, replaceHandler, delimiter); not available? You guys come up with some of the weirdest APIs I've ever seen. Gordon

  • Anonymous
    September 11, 2008
    Gordon: "stringify" is a standard; it's not Microsoft's name.

  • Anonymous
    September 11, 2008
    Why are we moving away from evalJson() ?

  • Anonymous
    September 11, 2008
    @Neil, @Gordon-- Different frameworks have different names for the functions.  The names selected for IE's native implementation are based by the ES3.1 proposal, which is in turn based on the most popular/definitive implementation, Douglas Crockford's json2.js. @Tino: RFC4627 covers the wire format for the application/json media type.  It's not applicable in this case because the script engine isn't working with a wire format/media type, it's working with a Unicode string.  Internally, IE (and I'd imagine most browsers) decode from wire formats into Unicode (UTF16 in our case) and then convert back into encoded formats only as needed.  Therefore, your server needs only to return a string in some encoding with the proper encoding specified, then XMLHTTPRequest or XDomainRequest (or whatever) will convert that string into Unicode, and that Unicode string will be handled by the parse() method.

  • Anonymous
    September 12, 2008
    @steve:” what happens when "naughty" JSON is encountered?”. -- A: If your code doesn’t define the JSON object, a reference to JSON returns the builtin JSON object. You might have a problem only if your code relies on JSON being undefined. If your code defines the JSON object, most probably you override it and you have no problem. If you define your own JSON object conditionally like “if(!this.JSON){ JSON=…}” then the builtin JSON object is visible in your code. An expression like “JSON.encode()” might fail because the builtin object doesn’t have the function “encode”. @paul – right,  it is undefined.

  • Anonymous
    September 15, 2008
    before someone else asks: why won't the IE team look at how other browsers store wire formats? Gecko and KHTML/Webkit are open! Answer: there would be a risk that looking at these code may lead to some form of copyright infringement. Suggestion: why not ask in Gecko and/or Webkit mailing lists how these browsers encode it? Question: UTF16 (2 bytes per character) is a bit... wasteful, isn't it? At the same time, as far as I know, it doesn't cover all characters. Other question: what now happens on UTF-8 encoded documents that get the MS non-standard UTF8 prologue (reversed question mark etc.) ? This may actually cause trouble here if the stream was originally such a document.

  • Anonymous
    September 18, 2008
    As you might be aware that Internet Explorer Beta 2 was released few weeks back. In this JScript team

  • Anonymous
    October 05, 2008
    You've been kicked (a good thing) - Trackback from DotNetKicks.com

  • Anonymous
    December 12, 2008
    I was testing out some typography with Silverlight and figured I’d try grab some text from Wikipedia

  • Anonymous
    January 13, 2009
    As a Program Manager, I love to write feature specifications (that’s a job description requirement)!

  • Anonymous
    January 25, 2009
    Обновленный синтаксис Getters/Setters в IE8 RC1 Как программному менеджеру, мне нравится писать спецификации

  • Anonymous
    March 12, 2009
    Reports of broken sites are an important part of the feedback the IE team receives from the community.

  • Anonymous
    March 16, 2009
        이 글의 제목을 보고 아셨을지 모르겠지만, Internet Explorer 8 은 Beta 2에서 네이티브 JSON 구문해석기능과 serialization

  • Anonymous
    March 24, 2009
    During Beta1 and Beta2 pre-releases of IE8, we’ve blogged about the performance optimizations done in

  • Anonymous
    March 24, 2009
    During Beta1 and Beta2 pre-releases of IE8, we’ve blogged about the performance optimizations done in

  • Anonymous
    April 09, 2009
    In the world of web standards, JavaScript is known as ECMAScript and maintenance of its definition is

  • Anonymous
    April 12, 2009
    Native JSON parsing and serialization is a new feature to IE8 and Firefox 3.5 and makes evaling a thing

  • Anonymous
    April 16, 2009
    With Internet Explorer 8 we introduced several new JScript language features including native JSON support

  • Anonymous
    May 08, 2009
    I had a great time this week speaking to the Atlanta PHP user group about our new Web Platform gallery