我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?
谢谢
var obj = {
a: "foo",
b: obj
}
我想将对象字符串化为:
{"a":"foo"}
我有一个大对象要转换成JSON并发送。然而,它具有圆形结构。我想丢弃任何存在的循环引用,并发送任何可以字符串化的引用。我该怎么做?
谢谢
var obj = {
a: "foo",
b: obj
}
我想将对象字符串化为:
{"a":"foo"}
当前回答
在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}])
请阅读下面的评论并给予表扬。。。
其他回答
我真的很喜欢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);
};
在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}])
请阅读下面的评论并给予表扬。。。
If
console.log(JSON.stringify(object));
结果是
TypeError:循环对象值
然后,您可能想要这样打印:
var output = '';
for (property in object) {
output += property + ': ' + object[property]+'; ';
}
console.log(output);
当你不知道所有循环引用的键时,对于未来搜索这个问题解决方案的谷歌用户,你可以使用JSON.stringify函数的包装器来排除循环引用。参见示例脚本https://gist.github.com/4653128.
解决方案本质上归结为在数组中保留对先前打印对象的引用,并在返回值之前在替换函数中检查该引用。它比仅排除循环引用更具限制性,因为它还排除了两次打印对象的可能性,其副作用之一是避免循环引用。
包装示例:
function stringifyOnce(obj, replacer, indent){
var printedObjects = [];
var printedObjectKeys = [];
function printOnceReplacer(key, value){
var printedObjIndex = false;
printedObjects.forEach(function(obj, index){
if(obj===value){
printedObjIndex = index;
}
});
if(printedObjIndex && typeof(value)=="object"){
return "(see " + value.constructor.name.toLowerCase() + " 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);
}
我建议从@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()来自定义净化行为。如果您发现自己需要一个简单的示例来说明如何做到这一点,我只是在这里编写了一个自定义替换器,它将错误、正则表达式和函数强制转换为人类可读的字符串。