JSON (JavaScript Object Notation) is a lightweight data-interchange format (if you are new to JSON, you can read more about it on theJSON website). It is notably used by APIs all over the web and is a fast alternative to XML in Ajax requests. Prototype 1.5.1 finally features JSON encoding and parsing support.
Prototype’s JSON implementation is largely based on the work ofDouglas Crockford which will most likely be natively included in future versions of the main browsers.Crockford’s implementation is unfortunately unsuitable for use with Prototype because of the way it extendsObject.prototype. (Note that this will no longer be an issue once it is natively implemented.)
Prototype’s JSON encoding slightly differs from Crockford’s implementation as it does not extendObject.prototype. The following methods are available:Number#toJSON,String#toJSON,Array#toJSON,Hash#toJSON,Date#toJSON, andObject.toJSON.
If you are unsure of what type the data you need to encode is, your best bet is to useObject.toJSON like so:
vardata={name:'Violet',occupation:'character',age:25};Object.toJSON(data);//-> '{"name": "Violet", "occupation": "character", "age": 25}'In other cases (i.e. if you know that your data isnot an instance ofObject), you can invoke thetoJSON method instead:
$H({name:'Violet',occupation:'character',age:25}).toJSON();//-> '{"name": "Violet", "occupation": "character", "age": 25}'Furthermore, if you are using custom objects, you can set your owntoJSON method which will be used byObject.toJSON. For example:
varPerson=Class.create({initialize:function(name,age){this.name=name;this.age=age;},toJSON:function(){return('My name is'+this.name+' and I am'+this.age+' years old.').toJSON();}});varjohn=newPerson('John',49);Object.toJSON(john);//-> '"My name is John and I am 49 years old."'Finally, usingElement.addMethods you can create customtoJSON methods targeted at specific elements.
<inputid="firstname"name="firstname"value="john"/>Element.addMethods('input',{toJSON:function(element){element=$(element);returnelement.name.toJSON()+":"+element.getValue().toJSON();}})Object.toJSON($('firstname'));//-> '"firstname": "john"'In JavaScript, parsing JSON is typically done by evaluating the content of a JSON string. Prototype introducesString#evalJSON to deal with this:
vardata='{ "name": "Violet", "occupation": "character" }'.evalJSON();data.name;//-> "Violet"String#evalJSON takes an optionalsanitize parameter, which, if set totrue, checks the string for possible malicious attempts and prevents the evaluation and throws aSyntaxError if one is detected.
vardata='grabUserPassword()'.evalJSON(true)//-> SyntaxError: Badly formated JSON string: 'grabUserPassword()'You should always set thesanitize parameter totrue and an appropriate content-type header (application/json) for data coming from untrusted sources (external or user-created content) to prevent XSS attacks.
String#evalJSON internally callsString#unfilterJSON and automatically removes optional security comment delimiters (defined inPrototype.JSONFilter).
person='/*-secure-\n{"name": "Violet", "occupation": "character"}\n*/'.evalJSON()person.name;//-> "Violet"You should always set security comment delimiters (/*-secure-\n...*/) around sensitive JSON or JavaScript data to prevent Hijacking. (Seethis PDF document for more details.)
Using JSON with Ajax is very straightforward, simply invokeString#evalJSON on the transport’sresponseText property:
newAjax.Request('/some_url',{method:'get',onSuccess:function(transport){varjson=transport.responseText.evalJSON();}});If your data comes from an untrusted source, be sure to sanitize it:
newAjax.Request('/some_url',{method:'get',requestHeaders:{Accept:'application/json'},onSuccess:function(transport){varjson=transport.responseText.evalJSON(true);}});© 2006–2023 Prototype Core Team.
Licenses:MIT License (source code) andCC-BY-SA (documentation)