我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?
谢谢
var obj = {
a: "foo",
b: obj
}
我想将对象字符串化为:
{"a":"foo"}
我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?
谢谢
var obj = {
a: "foo",
b: obj
}
我想将对象字符串化为:
{"a":"foo"}
当前回答
我为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": {}
}
}
}
其他回答
就这样吧
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是其继任者。
在Node.js中,您可以使用util.inspect(object)。它会自动将循环链接替换为“[circular]”。
尽管是内置的(不需要安装),但必须导入它
import * as util from 'util' // has no default export
import { inspect } from 'util' // or directly
// or
var util = require('util')
要使用它,只需调用
console.log(util.inspect(myObject))
还要注意,您可以传递options对象以进行检查(请参见上面的链接)
inspect(myObject[, options: {showHidden, depth, colors, showProxy, ...moreOptions}])
请阅读下面的评论并给予表扬。。。
这里有一个解决方案:
仅删除循环(而不是所有重复的对象引用,到目前为止这里发布的大多数解决方案也是如此),不是不必要的冗长,速度快,不需要任何库依赖关系。
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]'}}"
我想知道为什么还没有人从MDN页面发布正确的解决方案。。。
const circular Reference={otherData:123};circular Reference.imy=circular参考;常量getCircularReplacer=()=>{const seed=new WeakSet();return(键,值)=>{if(typeof value==“object”&&value!==null){if(seed.has(value)){回来}见add(值);}返回值;};};const stringified=JSON.stringify(circularReference,getCircularReplacer());console.log(字符串化);
Seen值应该存储在集合中,而不是数组中(每个元素都会调用replacer)。
与公认的答案一样,此解决方案删除了所有重复值,而不仅仅是循环值。但至少它没有指数级的复杂性。
我知道这个问题很老,有很多很好的答案,但我发布这个答案是因为它有新的味道(es5+)
Object.defineProperties(JSON{refStringify:{值:函数(obj){let objMap=new Map();let stringified=JSON.stringify(obj,函数(键、值){//仅适用于对象if(值类型==“对象”){//如果具有值,则返回对它的引用if(objMap.has(value))return objMap.get(value);objMap.set(值,`ref${objMap.size+1}`);}返回值;});返回字符串;}},参考解析:{value:函数(str){let parsed=JSON.parse(str);let objMap=_createObjectMap(已解析);objMap.forEach((value,key)=>_replaceKeyWithObject(value,key));返回解析;}},});//***************************示例设a={b: 32中,c:{获取a(){返回a;},获取c(){返回a.c;}}};let stringified=JSON.refStringify(a);let parsed=JSON.refParse(字符串化,2);console.log(已解析,JSON.refStringify(已解析));//***************************/示例//***************************助手函数_createObjectMap(obj){let objMap=new Map();JSON.stringify(obj,(key,value)=>{if(值类型==“对象”){if(objMap.has(value))return objMap.get(value);objMap.set(值,`ref${objMap.size+1}`);}返回值;});返回objMap;}函数_replaceKeyWithObject(key,obj,replaceWithObject=obj){Object.keys(obj).forEach(k=>{设val=obj[k];if(val==键)return(obj[k]=replaceWithObject);if(typeof val=='object'&&val!=replaceWithObject)_replaceKeyWithObject(key,val,replaceWithObject);});}