migrating to Prototype's native JSON

written by Tobie on March 15th, 2007 @ 06:53 AM

Since version 1.5.1_rc0, Prototype comes with native JSON support. The main idea behind this implementation was to offer an alternative to Douglas Crockford's implementation, which is designed to be natively included in future versions of JavaScript and thus extends Object.prototype, causing mayhem in for...in loops.

Migrating to Prototype's JSON implementation is a piece of cake and should take you about five minutes.

  1. Locate all your instances of something.toJSONString() and replace them with Object.toJSON(something). For example:

    {name: 'Joe', type: 'human'}.toJSONString();
    // becomes: 
    Object.toJSON({name: 'Joe', type: 'human'});
    
  2. Locate all your instances of something.parseJSON() and replace them with something.evalJSON():

    '{"name":"Joe","type":"human"}'.parseJSON();
    // becomes: 
    '{"name":"Joe","type":"human"}'.evalJSON();
    

    Note that, if you do not trust the source of your data (external, user created), you must set the sanitize option to true (see the documentation for more details).

    '{"name":"Joe","type":"human"}'.parseJSON();
    // becomes: 
    '{"name":"Joe","type":"human"}'.evalJSON(true); // <- sanitize is set to true
    

    In the rare case where you were actually using the filter option provided by Crockford's implementation, you can either iterate over each property of your object, or simply add Crockford's String#parseJSON method to your JavaScript files like so, (and this won't mess with Object.prototype, so its fine to do so):

    String.prototype.parseJSON = function (filter) {
      try {
        if (/^("(\.|[^"\\n\r])*?"|[,:{}[]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(this)) {
          var j = eval('(' + this + ')');
          if (typeof filter === 'function') {
            function walk(k, v) {
              if (v && typeof v === 'object') {
                for (var i in v) {
                  if (v.hasOwnProperty(i)) v[i] = walk(i, v[i]);
                }
              }
              return filter(k, v);
            }
            j = walk('', j);
          }
          return j;
        }
      } catch (e) {}
      throw new SyntaxError("parseJSON");
    };
    

That's it.

Obviously, as soon as browsers will start implementing Crockford's methods, we'll tweak Prototype to make sure we take advantage of the native implementation.

Comments are closed