-
-
Save NHQ/3385135 to your computer and use it in GitHub Desktop.
object JSON serialization that's circular-ref safe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// all this `toJSON()` does is filter out any circular refs. all other values/refs, | |
// it passes through untouched, so it should be totally safe. see the test examples. | |
Object.prototype.toJSON = function() { | |
function findCircularRef(obj) { | |
for (var i=0; i<refs.length; i++) { | |
if (refs[i] === obj) return true; | |
} | |
return false; | |
} | |
function traverse(obj) { | |
function element(el) { | |
if (typeof el === "object") { | |
if (el !== null) { | |
if (Date === el.constructor || Number === el.constructor || Boolean === el.constructor || String === el.constructor || RegExp === el.constructor) { | |
return el; | |
} | |
else if (!findCircularRef(el)) { | |
return traverse(el); | |
} | |
} | |
return null; | |
} | |
return el; | |
} | |
var idx, tmp, tmp2; | |
if (Object.prototype.toString.call(obj) === "[object Array]") { | |
refs.push(obj); | |
tmp = []; | |
for (idx=0; idx<obj.length; idx++) { | |
tmp.push(element(obj[idx])); | |
} | |
refs.pop(); | |
return tmp; | |
} | |
else if (typeof obj === "object") { | |
if (obj !== null) { | |
if (Date === obj.constructor || Number === obj.constructor || String === obj.constructor || Boolean === obj.constructor || RegExp === obj.constructor) { | |
return obj; | |
} | |
else if (!findCircularRef(obj)) { | |
refs.push(obj); | |
tmp = {}; | |
for (idx in obj) { if (obj.hasOwnProperty(idx)) { | |
tmp2 = element(obj[idx]); | |
if (tmp2 !== null) tmp[idx] = tmp2; | |
}} | |
refs.pop(); | |
return tmp; | |
} | |
} | |
return null; | |
} | |
else return obj; | |
} | |
var refs = [], ret; | |
ret = traverse(this); | |
refs = []; | |
return ret; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var a = { | |
b: 12, | |
c: true, | |
d: "foobar", | |
e: { | |
f: function() { alert("blah"); }, // functions get ignored | |
g: new Date(), // dates get their own `toJSON()` serialization called | |
h: [ true,1.3,"haha" ] | |
}, | |
k: {}, | |
l: /foobar/g // regexes get turned into an empty {} | |
}; | |
a.i = a; // circular ref!! | |
a.e.i = a; // circular ref!! | |
a.e.j = a.e; // circular ref!! | |
a.e.h.push(a.e); // circular ref!! since it's in array, will be replaced with `null` | |
a.k.m = a.e; // **NOT** a circular ref, just a dupe ref, so leave it alone!! | |
// Look Ma! No circular refs! | |
JSON.stringify(a); // {"b":12,"c":true,"d":"foobar","e":{"g":"2012-08-17T12:11:05.647Z","h":[true,1.3,"haha",null]},"k":{"m":{"g":"2012-08-17T12:11:05.647Z","h":[true,1.3,"haha",null]}},"l":{}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment