我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?
谢谢
var obj = {
a: "foo",
b: obj
}
我想将对象字符串化为:
{"a":"foo"}
我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?
谢谢
var obj = {
a: "foo",
b: obj
}
我想将对象字符串化为:
{"a":"foo"}
当前回答
试试看:
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);
其他回答
我建议从@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()来自定义净化行为。如果您发现自己需要一个简单的示例来说明如何做到这一点,我只是在这里编写了一个自定义替换器,它将错误、正则表达式和函数强制转换为人类可读的字符串。
我真的很喜欢Trindaz的解决方案——更详细,但它有一些缺陷。我也为喜欢它的人修过。
此外,我对缓存对象添加了长度限制。
如果我打印的对象真的很大-我的意思是无限大-我想限制我的算法。
JSON.stringifyOnce = function(obj, replacer, indent){
var printedObjects = [];
var printedObjectKeys = [];
function printOnceReplacer(key, value){
if ( printedObjects.length > 2000){ // browsers will not print more than 20K, I don't see the point to allow 2K.. algorithm will not be fast anyway if we have too many objects
return 'object too long';
}
var printedObjIndex = false;
printedObjects.forEach(function(obj, index){
if(obj===value){
printedObjIndex = index;
}
});
if ( key == ''){ //root element
printedObjects.push(obj);
printedObjectKeys.push("root");
return value;
}
else if(printedObjIndex+"" != "false" && typeof(value)=="object"){
if ( printedObjectKeys[printedObjIndex] == "root"){
return "(pointer to root)";
}else{
return "(see " + ((!!value && !!value.constructor) ? value.constructor.name.toLowerCase() : typeof(value)) + " with key " + printedObjectKeys[printedObjIndex] + ")";
}
}else{
var qualifiedKey = key || "(empty key)";
printedObjects.push(value);
printedObjectKeys.push(qualifiedKey);
if(replacer){
return replacer(key, value);
}else{
return value;
}
}
}
return JSON.stringify(obj, printOnceReplacer, indent);
};
就这样吧
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": {}
}
}
}
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}