Skip to content

Instantly share code, notes, and snippets.

@tsaniel
Forked from 140bytes/LICENSE.txt
Created July 17, 2011 07:37
Show Gist options
  • Save tsaniel/1087317 to your computer and use it in GitHub Desktop.
Save tsaniel/1087317 to your computer and use it in GitHub Desktop.
JSON stringify

JSON stringify

A simple JSON stringify function which requires Array.prototype.map method.

Contributors

The following users provided lots of ideas and improvements of the code.

@Kambfhase, @hartrock, @atk, @haochi, @jed

Actually, I just provided a deficient version at first. The other versions were created by these users(especially @atk). You may see the discussion below.

function f(
a, // input (expect object)
b, // placeholder
c // placeholder
){
for (b in
// if the input is an object, assign an empty array to c and loop through the properties of it;
// otherwise assign false to c and iterate over nothing.
// but since it's just a roughly checking, a string "[object Object]" will falsely be identified as object,
// and starts the iteration in most of the browsers -
// as properties on strings can be accessed like arrays(except lower IE version, e.g. IE7).
// (reference: http://kangax.github.com/es5-compat-table/#property-access-on-strings).
// anyway, the function still works although there may be unwanted loopings with a bit slower.
(c = a == '' + {} && []) && a
)
// fill array with object-style key: value pairs, call ourself recursively to escape keys and values.
c.push(f(b) + ':' + f(a[b]));
// check if the input is a string,
return '' + a === a ?
// output as a string literal;
'"' + a + '"' :
// otherwise check if the input is present and an array (has .map),
a && a.map ?
// output as an array literal;
'[' + a.map(f) + ']' :
// otherwise check if the input is an object (c is an array rather than false),
c ?
// output as an object literal;
'{' + c + '}' :
// otherwise use plain coercion (mostly for number/boolean/null literals).
a
}
function f(a,b,c){for(b in(c=a==""+{}&&[])&&a)c.push(f(b)+":"+f(a[b]));return""+a===a?'"'+a+'"':a&&a.map?"["+a.map(f)+"]":c?"{"+c+"}":a}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 YOUR_NAME_HERE <YOUR_URL_HERE>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "JSON stringify",
"description": "A JSON stringify function",
"keywords": [
"JSON",
"stringify"
]
}
<!DOCTYPE html>
<title>JSON stringify</title>
<div>Expected value: <b>{"a":123,"b":true,"c":false,"d":null,"e":{"a":"some text"},"f":[1,2,3],"g":["eins","zwei","drei"],"h":[{"one":1},{"one":1,"two":2}],"i":[{"one":1},{"one":1,"two":[{"three":3},[1,2,3]]}]}</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
var myFunction = function f(a,b,c){for(b in(c=a==""+{}&&[])&&a)c.push(f(b)+":"+f(a[b]));return""+a===a?'"'+a+'"':a&&a.map?"["+a.map(f)+"]":c?"{"+c+"}":a};
document.getElementById( "ret" ).innerHTML = myFunction({
a: 123,
b: true,
c: false,
d: null,
e: {a: "some text"},
f: [1, 2, 3],
g: ["eins", "zwei", "drei"],
h: [{one:1}, {"one":1, two:2}],
i: [{one:1}, { "one":1, two:[ {three:3}, [1,2,3] ] } ]
})
</script>
@tkissing
Copy link

Ah, right. Bummer. And .trim won't work in older JS implementations. Too bad...

@tsaniel
Copy link
Author

tsaniel commented Nov 11, 2011

And so is Array#map...

@atk
Copy link

atk commented Nov 11, 2011

But Array#map will work in node.js - and for older implementations we already have a working polyfill.

@tsaniel
Copy link
Author

tsaniel commented Nov 11, 2011

In that way, we have polyfill for trim as well.

@adius
Copy link

adius commented Mar 7, 2012

You should use a.pop instead of a.map as in DOMinate. Much better browser compatibility!

@atk
Copy link

atk commented Mar 9, 2012

@adius: doesn't help, because we'll need a.map anyway. A working version (alas, with 214bytes too long) is here:

function s(a,b,c){for(b in(c=a==''+{}&&[])&&a)c.push(s(b)+':'+s(a[b]));return''+a===a?'"'+a.replace(/[\x00-\x32\\]/g,function(x){return'\x'+x.charCodeAt().toString(16)})+'"':a&&a.map?'['+a.map(s)+']':c?'{'+c+'}':a}

I've not yet tested if it still works if you replace function(x){return'\x'+x.charCodeAt().toString(16)} with function(x){return escape(x).replace(/%/g,'\\x')}, saving 2 further bytes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment