JSON.stringify, avoid TypeError: Converting circular structure to JSON

I have a big object I want to convert to JSON and send. However it has circular structure. I want to toss whatever circular references exist and send whatever can be stringified. How do I do that?

Thanks.

var obj = {
  a: "foo",
  b: obj
}

I want to stringify obj into:

{"a":"foo"}

Use JSON.stringify with a custom replacer. For example:

// Demo: Circular reference
var o = {};
o.o = o;

// Note: cache should not be re-used by repeated calls to JSON.stringify.
var cache = [];
JSON.stringify(o, function(key, value) {
    if (typeof value === 'object' && value !== null) {
        if (cache.indexOf(value) !== -1) {
            // Circular reference found, discard key
            return;
        }
        // Store value in our collection
        cache.push(value);
    }
    return value;
});
cache = null; // Enable garbage collection

The replacer in this example is not 100% correct (depending on your definition of "duplicate"). In the following case, a value is discarded:

var a = {b:1}
var o = {};
o.one = a;
o.two = a;
// one and two point to the same object, but two is discarded:
JSON.stringify(o, ...);

But the concept stands: Use a custom replacer, and keep track of the parsed object values.


In Node.js, you can use util.inspect(object). It automatically replaces circular links with "[Circular]".


I really liked Trindaz's solution - more verbose, however it had some bugs. I fixed them for whoever likes it too.

Plus, I added a length limit on my cache objects.

If the object I am printing is really big - I mean infinitely big - I want to limit my algorithm.

JSON.stringifyOnce = function(obj, replacer, indent){
    var printedObjects = [];
    var printedObjectKeys = [];

    function printOnceReplacer(key, value){
        if ( printedObjects.length > 2000){ // browsers will not print more than 20K, I don't see the point to allow 2K.. algorithm will not be fast anyway if we have too many objects
        return 'object too long';
        }
        var printedObjIndex = false;
        printedObjects.forEach(function(obj, index){
            if(obj===value){
                printedObjIndex = index;
            }
        });

        if ( key == ''){ //root element
             printedObjects.push(obj);
            printedObjectKeys.push("root");
             return value;
        }

        else if(printedObjIndex+"" != "false" && typeof(value)=="object"){
            if ( printedObjectKeys[printedObjIndex] == "root"){
                return "(pointer to root)";
            }else{
                return "(see " + ((!!value && !!value.constructor) ? value.constructor.name.toLowerCase()  : typeof(value)) + " with key " + printedObjectKeys[printedObjIndex] + ")";
            }
        }else{

            var qualifiedKey = key || "(empty key)";
            printedObjects.push(value);
            printedObjectKeys.push(qualifiedKey);
            if(replacer){
                return replacer(key, value);
            }else{
                return value;
            }
        }
    }
    return JSON.stringify(obj, printOnceReplacer, indent);
};
链接地址: http://www.djcxy.com/p/48228.html

上一篇: 什么是$ $$ hashKey添加到我的JSON.stringify结果

下一篇: JSON.stringify,避免TypeError:将循环结构转换为JSON