序列化包含循环对象值的对象
序列化包含循环对象值的对象
我有一个包含子节点引用其他节点的对象(解析树)。
我想使用JSON.stringify()
对这个对象进行序列化,但我遇到了
TypeError: cyclic object value
因为我提到的结构。
我该如何解决这个问题?对我来说,这些引用其他节点的引用是否在序列化的对象中表示都无所谓。
另一方面,在创建这些属性时从对象中删除它们似乎很繁琐,我也不想对解析器(narcissus)进行更改。
admin 更改状态以发布 2023年5月22日
这篇文章的替代方案有点不同,但由于很多人会来这里调试他们的循环对象,没有一个很好的方法不需要引入大量的代码进行调试,所以我们来试试。
一个不太广为人知的特性是JSON.stringify()
,console.table()
比这个更好。只需要调用console.table(whatever);
,它会以表格的形式在控制台中记录变量,这使得浏览变量的内容变得非常容易和方便。
使用stringify
的第二个参数,即替换函数来排除已经序列化的对象:
var seen = []; JSON.stringify(obj, function(key, val) { if (val != null && typeof val == "object") { if (seen.indexOf(val) >= 0) { return; } seen.push(val); } return val; });
正如其他评论中正确指出的那样,此代码将删除每个“已看到”的对象,而不仅仅是“递归”的对象。
例如:
a = {x:1}; obj = [a, a];
结果将是不正确的。如果您的结构是这样的,您可能希望使用Crockford的decycle或这个(更简单的)函数,仅将递归引用替换为null:
function decycle(obj, stack = []) { if (!obj || typeof obj !== 'object') return obj; if (stack.includes(obj)) return null; let s = stack.concat([obj]); return Array.isArray(obj) ? obj.map(x => decycle(x, s)) : Object.fromEntries( Object.entries(obj) .map(([k, v]) => [k, decycle(v, s)])); } // let a = {b: [1, 2, 3]} a.b.push(a); console.log(JSON.stringify(decycle(a)))