As per the JSON docs at Mozilla, JSON.stringify has a second parameter replacer which can be used to filter/ignore children items while parsing the tree. However, perhaps you can avoid the circular references.
In Node.js we cannot. So we can do something like this:
function censor(censor) { var i = 0; return function(key, value) { if(i !== 0 && typeof(censor) === 'object' && typeof(value) == 'object' && censor == value) return '[Circular]'; if(i >= 29) // seems to be a harded maximum of 30 serialized objects? return '[Unknown]'; ++i; // so we know we aren't using the original object anymore return value; } } var b = {foo: {bar: null}}; b.foo.bar = b; console.log("Censoring: ", b); console.log("Result: ", JSON.stringify(b, censor(b)));
The result:
Censoring: { foo: { bar: [Circular] } } Result: {"foo":{"bar":"[Circular]"}}
Unfortunately there seems to be a maximum of 30 iterations before it automatically assumes it's circular. Otherwise, this should work. I even used areEquivalent from here, but JSON.stringify still throws the exception after 30 iterations. Still, it's good enough to get a decent representation of the object at a top level, if you really need it. Perhaps somebody can improve upon this though? In Node.js for an HTTP request object, I'm getting:
{ "limit": null, "size": 0, "chunks": [], "writable": true, "readable": false, "_events": { "pipe": [null, null], "error": [null] }, "before": [null], "after": [], "response": { "output": [], "outputEncodings": [], "writable": true, "_last": false, "chunkedEncoding": false, "shouldKeepAlive": true, "useChunkedEncodingByDefault": true, "_hasBody": true, "_trailer": "", "finished": false, "socket": { "_handle": { "writeQueueSize": 0, "socket": "[Unknown]", "onread": "[Unknown]" }, "_pendingWriteReqs": "[Unknown]", "_flags": "[Unknown]", "_connectQueueSize": "[Unknown]", "destroyed": "[Unknown]", "bytesRead": "[Unknown]", "bytesWritten": "[Unknown]", "allowHalfOpen": "[Unknown]", "writable": "[Unknown]", "readable": "[Unknown]", "server": "[Unknown]", "ondrain": "[Unknown]", "_idleTimeout": "[Unknown]", "_idleNext": "[Unknown]", "_idlePrev": "[Unknown]", "_idleStart": "[Unknown]", "_events": "[Unknown]", "ondata": "[Unknown]", "onend": "[Unknown]", "_httpMessage": "[Unknown]" }, "connection": "[Unknown]", "_events": "[Unknown]", "_headers": "[Unknown]", "_headerNames": "[Unknown]", "_pipeCount": "[Unknown]" }, "headers": "[Unknown]", "target": "[Unknown]", "_pipeCount": "[Unknown]", "method": "[Unknown]", "url": "[Unknown]", "query": "[Unknown]", "ended": "[Unknown]" }
I created a small Node.js module to do this here: https://github.com/highruned/stringy Feel free to improve/contribute!
pagedoc?pagedoc? 2. Circular reference:a = {}; a.b = a;