我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?
谢谢
var obj = {
a: "foo",
b: obj
}
我想将对象字符串化为:
{"a":"foo"}
我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?
谢谢
var obj = {
a: "foo",
b: obj
}
我想将对象字符串化为:
{"a":"foo"}
当前回答
我这样解决这个问题:
var util = require('util');
// Our circular object
var obj = {foo: {bar: null}, a:{a:{a:{a:{a:{a:{a:{hi: 'Yo!'}}}}}}}};
obj.foo.bar = obj;
// Generate almost valid JS object definition code (typeof string)
var str = util.inspect(b, {depth: null});
// Fix code to the valid state (in this example it is not required, but my object was huge and complex, and I needed this for my case)
str = str
.replace(/<Buffer[ \w\.]+>/ig, '"buffer"')
.replace(/\[Function]/ig, 'function(){}')
.replace(/\[Circular]/ig, '"Circular"')
.replace(/\{ \[Function: ([\w]+)]/ig, '{ $1: function $1 () {},')
.replace(/\[Function: ([\w]+)]/ig, 'function $1(){}')
.replace(/(\w+): ([\w :]+GMT\+[\w \(\)]+),/ig, '$1: new Date("$2"),')
.replace(/(\S+): ,/ig, '$1: null,');
// Create function to eval stringifyed code
var foo = new Function('return ' + str + ';');
// And have fun
console.log(JSON.stringify(foo(), null, 4));
其他回答
就这样吧
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是其继任者。
此解决方案修复了用户2451227报告的接受答案问题(当o={};JSON.stringify([o,o],getCircularReplacer()))。
函数newCircularReplacer(){常量seenValues=[]返回循环替换器函数circleReplacer(键,值){if(typeof value=='object'&&value!==null&&object.keys(value).length){常量堆栈大小=参见值长度if(堆栈大小){for(设n=stackSize-1;参见nValues[n][key]!==value;--n)seenValues.pop()//清除过期的引用if(参见nValues.includes(value))返回'[Circular]'}参见值push(value)}返回值}}设o={a:1}o.b=o//循环参考控制台日志(JSON.stringify(o,newCircularReplacer())//{a:1,b:[Circular]}✅)o={}a=[o,o]//非循环参考控制台日志(JSON.stringify(a,newCircularReplacer())//[{},{}]✅)
试试看:
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);
var a={b:"b"};
a.a=a;
JSON.stringify(preventCircularJson(a));
评估结果为:
"{"b":"b","a":"CIRCULAR_REFERENCE_REMOVED"}"
具有以下功能:
/**
* Traverses a javascript object, and deletes all circular values
* @param source object to remove circular references from
* @param censoredMessage optional: what to put instead of censored values
* @param censorTheseItems should be kept null, used in recursion
* @returns {undefined}
*/
function preventCircularJson(source, censoredMessage, censorTheseItems) {
//init recursive value if this is the first call
censorTheseItems = censorTheseItems || [source];
//default if none is specified
censoredMessage = censoredMessage || "CIRCULAR_REFERENCE_REMOVED";
//values that have allready apeared will be placed here:
var recursiveItems = {};
//initaite a censored clone to return back
var ret = {};
//traverse the object:
for (var key in source) {
var value = source[key]
if (typeof value == "object") {
//re-examine all complex children again later:
recursiveItems[key] = value;
} else {
//simple values copied as is
ret[key] = value;
}
}
//create list of values to censor:
var censorChildItems = [];
for (var key in recursiveItems) {
var value = source[key];
//all complex child objects should not apear again in children:
censorChildItems.push(value);
}
//censor all circular values
for (var key in recursiveItems) {
var value = source[key];
var censored = false;
censorTheseItems.forEach(function (item) {
if (item === value) {
censored = true;
}
});
if (censored) {
//change circular values to this
value = censoredMessage;
} else {
//recursion:
value = preventCircularJson(value, censoredMessage, censorChildItems.concat(censorTheseItems));
}
ret[key] = value
}
return ret;
}
我们使用对象扫描进行数据处理,这可能是一个可行的解决方案。这就是它的工作方式(也可以正确修剪数组)
.作为控制台包装{最大高度:100%!重要;顶部:0}<script type=“module”>导入对象扫描自'https://cdn.jsdelivr.net/npm/object-scan@18.1.2/lib/index.min.js';const prune=(data)=>对象扫描(['**']{rtn:'计数',filterFn:({isCircular,父级,属性})=>{if(isCircular){if(Array.isArray(父级)){parent.splice(属性,1);}其他{删除父项[属性];}返回true;}return false;},breakFn:({isCircular})=>isCircular==true})(数据);常量obj={a:'foo',c:[0]};obj.b=对象;obj.c.push(obj);console.log(obj);//=><ref*1>{a:'foo',c:[0,[Circular*1]],b:[Circulal*1]}console.log(prune(obj));//返回循环计数// => 2console.log(obj);//=>{a:'foo',c:[0]}</script>
免责声明:我是物体扫描的作者