Sunday, September 09, 2007

Worlds Smallest toJson Function

While a google search of "toJSON javascript" revealed a few functions to convert javascript objects into strings, I was sadly dissappointed to see that most of them prototyped object its self (which you will recall every javascript object is prototyped from) The general opinion of those javascript developers that I respect is that tampering with Object.prototype is verboten. Once you mess with Object.prototype, you have to do the following in all of your for-in loops:

for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
// Do Something
}
}

Adding two lines isn't a huge deal, but again, seems like unnecessary overhead to me, especially since Object is rarely what I need to prototype, and prototyping Array and String still lets you use Object as a hash.

So back to toJSON. I decided since I couldn't find a json parser that didn't prototype Object, I would write my own. This one is pretty basic, but here goes:





function toJson(obj) {
switch (typeof obj) {
case 'object':
if (obj) {
var list = [];
if (obj instanceof Array) {
for (var i=0;i < obj.length;i++) {
list.push(toJson(obj[i]));
}
return '[' + list.join(',') + ']';
} else {
for (var prop in obj) {
list.push('"' + prop + '":' + toJson(obj[prop]));
}
return '{' + list.join(',') + '}';
}
} else {
return 'null';
}
case 'string':
return '"' + obj.replace(/(["'])/g, '\\$1') + '"';
case 'number':
case 'boolean':
return new String(obj);
}
}


At least its short, all of the other parsers were much larger. Also note that my escaping and such is pretty basic, and probably needs some improvement, but this served my purpose, and again was small.

4 comments:

ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ said...

I wrote something similar in PHP :)

Seth A. Roby said...

case 'string':
return '"' + obj.replace(/(["'])/g, '\\$1') + '"';

That really doesn't need to be as complicated as it is here: the string will be surrounded in double quotes, so those are the only ones that need to be escaped using the replace. Simpler:

case 'string':
return '"' + this.replace(/"/g, '\\"') + '"';

sinni800 said...

Says "out of memory" at

list.push('"' + prop + '":' + toJson(obj[prop]));

for me ;)

Unknown said...

Is this intentional:

var a=[];
a["foo"] = "bar";
toJson(a) //=> "[]"

I've always thought that in Javascript arrays and hashes are the same thing, but apparently it's more complicated.