Skip to content

Instantly share code, notes, and snippets.

@gionkunz
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gionkunz/6d42acb21e9ec44fbc05 to your computer and use it in GitHub Desktop.
Save gionkunz/6d42acb21e9ec44fbc05 to your computer and use it in GitHub Desktop.
JSON generator with circular reference censoring
function flatten(s, stack) {
if(s === undefined || s === null || (typeof s === 'number' && isNaN(s))) {
return 'null';
} else if(s instanceof Date) {
return flatten(s.toJSON(), stack);
} else if(typeof s === 'object') {
stack = stack ? {obj: s, parent: stack} : {obj: s};
if((function cyclic(obj, stack, found) {
return found ||
(stack.parent ? cyclic(obj, stack.parent, stack.parent.obj === obj) : false);
}(s, stack))) {
return flatten('[circular reference]');
} else if(s instanceof Array) {
return ['[', s.map(function(v) {
return flatten(v, stack);
}).join(','), ']'].join('');
} else {
return ['{', Object.keys(s).filter(function(key) {
return s[key] !== undefined;
}).map(function(key) {
return ['"', key, '"', ':', flatten(s[key], stack)].join('');
}).join(','), '}'].join('');
}
} else if (typeof s === 'string') {
return ['"', s, '"'].join('');
} else {
return s;
}
}
@gionkunz
Copy link
Author

After I didn't find a satisfying solution to compare simple data objects, and I've found that comparing JSON strings is a very simple and nice way to compare simple data structures, I came up with this solution to generate JSON while sanitizing circular references. I found existing solutions with object re-occurrence checks not ideal as they don't take into account the object hierarchy. This solution is keeping track of the "call stack" with a stack object during the recursive calls and tracing back to parent stacks for circular reference detection.

You can play around with this function here: http://jsbin.com/hefis/3/edit

I did not check the JSON.stringify implementations and therefore don't know if I missed something in the conversion process. Please comment if you have any suggestions.

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