我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?

谢谢

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

我想将对象字符串化为:

{"a":"foo"}

当前回答

试试看:

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

var circular_replacer = (value) => {
    var seen = [];
    if (value != null && typeof value == "object") {
        if (seen.indexOf(value) >= 0) return;
        seen.push(value);
    }
    return value;
};

obj = circular_replacer(obj);

其他回答

要更新重写JSON工作方式的答案(可能不推荐,但非常简单),不要使用循环JSON(已弃用)。相反,使用后续的,扁平的:

https://www.npmjs.com/package/flatted

借用了上面@user1541685的旧答案,但替换为新答案:

npm i—保存展平

然后在js文件中

const CircularJSON = require('flatted');
const json = CircularJSON.stringify(obj);

在Node.js中,您可以使用util.inspect(object)。它会自动将循环链接替换为“[circular]”。


尽管是内置的(不需要安装),但必须导入它

import * as util from 'util' // has no default export
import { inspect } from 'util' // or directly
// or 
var util = require('util')

要使用它,只需调用

console.log(util.inspect(myObject))

还要注意,您可以传递options对象以进行检查(请参见上面的链接)

inspect(myObject[, options: {showHidden, depth, colors, showProxy, ...moreOptions}])


请阅读下面的评论并给予表扬。。。

JSON.stringify()的第二个参数还允许您指定一个关键字名称数组,该数组应保存在数据中遇到的每个对象中。这可能不适用于所有用例,但却是一个简单得多的解决方案。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

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

var json = JSON.stringify(obj, ['a']);
console.log(json);
// {"a":"foo"}

注意:奇怪的是,OP中的对象定义在最新的Chrome或Firefox中没有抛出循环引用错误。这个答案中的定义被修改了,所以它确实抛出了一个错误。


当你不知道所有循环引用的键时,对于未来搜索这个问题解决方案的谷歌用户,你可以使用JSON.stringify函数的包装器来排除循环引用。参见示例脚本https://gist.github.com/4653128.

解决方案本质上归结为在数组中保留对先前打印对象的引用,并在返回值之前在替换函数中检查该引用。它比仅排除循环引用更具限制性,因为它还排除了两次打印对象的可能性,其副作用之一是避免循环引用。

包装示例:

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

    function printOnceReplacer(key, value){
        var printedObjIndex = false;
        printedObjects.forEach(function(obj, index){
            if(obj===value){
                printedObjIndex = index;
            }
        });

        if(printedObjIndex && typeof(value)=="object"){
            return "(see " + value.constructor.name.toLowerCase() + " 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);
}

使用此类对象解决此问题的另一种解决方案是使用此库

https://github.com/ericmuyser/stringy

它很简单,你可以在几个简单的步骤中解决这个问题。