我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?
谢谢
var obj = {
a: "foo",
b: obj
}
我想将对象字符串化为:
{"a":"foo"}
我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?
谢谢
var obj = {
a: "foo",
b: obj
}
我想将对象字符串化为:
{"a":"foo"}
当前回答
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');
}
其他回答
我建议从@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解析器库: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节点引用进行导航。
我是这个图书馆的作者
@RobW的答案是正确的,但这更有表现力!因为它使用了hashmap/set:
const customStringify = function (v) {
const cache = new Set();
return JSON.stringify(v, function (key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.has(value)) {
// Circular reference found
try {
// If this value does not reference a parent it can be deduped
return JSON.parse(JSON.stringify(value));
}
catch (err) {
// discard key if value cannot be deduped
return;
}
}
// Store value in our set
cache.add(value);
}
return value;
});
};
这里有一个解决方案:
仅删除循环(而不是所有重复的对象引用,到目前为止这里发布的大多数解决方案也是如此),不是不必要的冗长,速度快,不需要任何库依赖关系。
function replaceCycles(obj, replacement = undefined, seen = new WeakSet()) {
if (typeof obj === 'object')
if (seen.has(obj))
return replacement
else {
seen.add(obj)
const newObj = {}
for (const key in obj)
newObj[key] = replaceCycles(obj[key], replacement, seen)
seen.delete(obj)
return newObj
}
else
return obj
}
用法:
const a = {
b: 'v1',
c: {
d: 'v2'
}
}
a.e = a.c
a.c.f = a.c
console.log(JSON.stringify(replaceCycles(a, '[CYCLE]')))
输出:
"{'b':'v1','c':{'d':'v2','f':'[CYCLE]'},'e':{'d':'v2','f':'[CYCLE]'}}"
我在github上找到了循环json库,它很好地解决了我的问题。
我发现一些有用的好功能:
支持多平台使用,但到目前为止我只使用node.js测试了它。API是相同的,所以您需要做的就是将其包含并用作JSON替换。它有自己的解析方法,所以您可以将“循环”序列化数据转换回对象。