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

谢谢

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

我想将对象字符串化为:

{"a":"foo"}

当前回答

我建议从@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工作方式的答案(可能不推荐,但非常简单),不要使用循环JSON(已弃用)。相反,使用后续的,扁平的:

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

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

npm i—保存展平

然后在js文件中

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

使用带有替换符的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”(引用),并使用精确的等式检查(==)来验证循环引用。

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}

就这样吧

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是其继任者。

我为LoggingUtilities类创建了以下方法。以下方法获取源和目标对象,并通过给定的maxLevel将源分配给目标。

  static assignObjectByLevel(
    sourceObject: any,
    targetObject: any,
    currentLevel: number = 0,
    maxLevel: number = 3,
    showUndefinedValues = false
  ): any {
    if (currentLevel >= maxLevel) {
      return;
    }

    const objQueue = [];
    for (const key in sourceObject) {
      if (sourceObject.hasOwnProperty(key)) {
        const value = sourceObject[key];
        if (typeof value === "object") {
          objQueue.push({ key, value });
        } else {
          targetObject[key] = value;
        }
      } else {
        if (showUndefinedValues) {
          targetObject[key] = "undefined/null";
        }
      }
    }

    while (objQueue.length > 0) {
      const objVal = objQueue.pop();
      currentLevel++;
      targetObject[objVal.key] = {};
      this.assignObjectByLevel(
        objVal.value,
        targetObject[objVal.key],
        currentLevel,
        maxLevel,
        false
      );
    }
  }

用法示例:

   const logObjParam = {
      level1: "value1",
      level2: {
        value2: "value2",
        level3: {
          value3: "value3",
          level4: {
            value4: " value4",
            level5: {
              value5: " value5",
            },
          },
        },
      },
    };

 let logObj = {};
 this.assignObjectByLevel(logObjParam, logObj);

结果:

{
  "level1": "value1",
  "level2": {
    "value2": "value2",
    "level3": {
      "value3": "value3",
      "level4": {}
    }
  }
}