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

谢谢

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

我想将对象字符串化为:

{"a":"foo"}

当前回答

我知道这是一个老问题,但我想建议一个我创建的NPM包,叫做智能循环,它的工作方式与其他建议的方式不同。如果您使用的是大而深的对象,它特别有用。

一些功能包括:

将循环引用或对象内部简单重复的结构替换为导致其首次出现的路径(而不仅仅是字符串〔circular〕);通过在广度优先搜索中查找循环,该包确保了该路径尽可能小,这在处理非常大和深度的对象时非常重要,因为这些对象的路径可能非常长且难以遵循(JSON.stringify中的自定义替换是DFS);允许个性化替换,方便简化或忽略对象的不重要部分;最后,路径完全以访问引用字段所需的方式编写,这可以帮助您进行调试。

其他回答

虽然这已经得到了充分的回答,但您也可以在字符串化之前使用delete运算符显式删除所讨论的属性。

delete obj.b; 
const jsonObject = JSON.stringify(obj);

删除运算符

这将消除构建或维护复杂逻辑以删除循环引用的需要。

就这样吧

npm i --save circular-json

然后在js文件中

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

https://github.com/WebReflection/circular-json

注意:我与这个包裹无关。但我确实用它来做这个。

2020年更新

请注意,CircularJSON仅在维护中,flatted是其继任者。

function myStringify(obj, maxDeepLevel = 2) {
  if (obj === null) {
    return 'null';
  }
  if (obj === undefined) {
    return 'undefined';
  }
  if (maxDeepLevel < 0 || typeof obj !== 'object') {
    return obj.toString();
  }
  return Object
    .entries(obj)
    .map(x => x[0] + ': ' + myStringify(x[1], maxDeepLevel - 1))
    .join('\r\n');
}

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

https://github.com/ericmuyser/stringy

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

注意,还有一个由Douglas Crockford实现的JSON.decycle方法。看看他的cycle.js。这允许您对几乎任何标准结构进行字符串化:

var a = [];
a[0] = a;
a[1] = 123;
console.log(JSON.stringify(JSON.decycle(a)));
// result: '[{"$ref":"$"},123]'.

您也可以使用逆循环方法重新创建原始对象。因此,您不必从对象中删除循环来将其字符串化。

然而,这对于DOM节点(在现实生活中,这是周期的典型原因)不起作用。例如,这将抛出:

var a = [document.body];
console.log(JSON.stringify(JSON.decycle(a)));

我做了一个叉来解决这个问题(参见我的cycle.js叉)。这应该很好:

var a = [document.body];
console.log(JSON.stringify(JSON.decycle(a, true)));

注意,在我的fork中,JSON.decycle(变量)的工作方式与原始一样,当变量包含DOM节点/元素时,将抛出异常。

当您使用JSON.decycle(variable,true)时,您接受这样一个事实,即结果是不可逆的(retrocycle不会重新创建DOM节点)。但DOM元素在某种程度上应该是可识别的。例如,如果一个div元素有一个id,那么它将被替换为字符串“div#id of the element”。