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

谢谢

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

我想将对象字符串化为:

{"a":"foo"}

当前回答

superserial完全序列化JavaScript对象。

https://github.com/denostack/superserial

用法:

const serializer = new Serializer();

const nodes = [{ self: null as any, siblings: [] as any[] }, {
  self: null as any,
  siblings: [] as any[],
}];
nodes[0].self = nodes[0];
nodes[0].siblings = nodes;
nodes[1].self = nodes[1];
nodes[1].siblings = nodes;

const serialized = serializer.serialize(nodes);

console.log(serialized);

输出:

[$1,$2];{"self":$1,"siblings":$0};{"self":$2,"siblings":$0}

其他回答

使用带有替换符的JSON.stringify方法。有关详细信息,请阅读本文档。http://msdn.microsoft.com/en-us/library/cc836459%28v=vs.94%29.aspx

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

var replacement = {"b":undefined};

alert(JSON.stringify(obj,replacement));

找出用循环引用填充替换数组的方法。您可以使用typeof方法来查找属性的类型是否为“object”(引用),并使用精确的等式检查(==)来验证循环引用。

我建议从@isaacs中检查json字符串安全性——它在NPM中使用。

顺便说一下,如果你没有使用Node.js,你可以从源代码的相关部分复制并粘贴第4-27行。

要安装:

$ npm install json-stringify-safe --save

要使用:

// Require the thing
var stringify = require('json-stringify-safe');

// Take some nasty circular object
var theBigNasty = {
  a: "foo",
  b: theBigNasty
};

// Then clean it up a little bit
var sanitized = JSON.parse(stringify(theBigNasty));

这产生了:

{
  a: 'foo',
  b: '[Circular]'
}

注意,就像@Rob W提到的普通JSON.stringify函数一样,您也可以通过将“replacer”函数作为第二个参数传递给stringify()来自定义净化行为。如果您发现自己需要一个简单的示例来说明如何做到这一点,我只是在这里编写了一个自定义替换器,它将错误、正则表达式和函数强制转换为人类可读的字符串。

当你不知道所有循环引用的键时,对于未来搜索这个问题解决方案的谷歌用户,你可以使用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

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

您可以尝试JSON解析器库:treedoc。它支持循环引用,并使用引用消除重复对象。

纱线添加树文档

import {TD} from 'treedoc'
TD.stringify(obj);

如果您需要更多定制

import {TD, TDEncodeOption} from 'treedoc'

const opt = new TDEncodeOption();
opt.coderOption.setShowType(true).setShowFunction(true);
opt.jsonOption.setIndentFactor(2);
return TD.stringify(obj, opt);

查看器可以查看生成的JSON文件http://treedoc.org,支持通过JSON节点引用进行导航。

我是这个图书馆的作者