Har*_*rry 608 javascript json node.js
我有一个大对象,我想转换为JSON并发送.但它具有圆形结构.我想抛出任何存在的循环引用并发送任何可以进行字符串化的内容.我怎么做?
谢谢.
var obj = {
a: "foo",
b: obj
}
Run Code Online (Sandbox Code Playgroud)
我想将obj字符串化为:
{"a":"foo"}
Run Code Online (Sandbox Code Playgroud)
Ere*_*evi 627
在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')
Run Code Online (Sandbox Code Playgroud)
要使用它,只需致电
console.log(util.inspect(myObject))
Run Code Online (Sandbox Code Playgroud)
另请注意,您可以传递options对象进行检查(参见上面的链接)
inspect(myObject[, options: {showHidden, depth, colors, showProxy, ...moreOptions}])
Run Code Online (Sandbox Code Playgroud)
请阅读并向下面的评论者致敬...
Rob*_*b W 551
JSON.stringify与自定义替换器一起使用.例如:
// Demo: Circular reference
var circ = {};
circ.circ = circ;
// Note: cache should not be re-used by repeated calls to JSON.stringify.
var cache = [];
JSON.stringify(circ, function(key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Duplicate reference found, discard key
return;
}
// Store value in our collection
cache.push(value);
}
return value;
});
cache = null; // Enable garbage collection
Run Code Online (Sandbox Code Playgroud)
此示例中的替换程序不是100%正确(取决于您对"重复"的定义).在以下情况中,将丢弃一个值:
var a = {b:1}
var o = {};
o.one = a;
o.two = a;
// one and two point to the same object, but two is discarded:
JSON.stringify(o, ...);
Run Code Online (Sandbox Code Playgroud)
但概念是:使用自定义替换器,并跟踪解析的对象值.
Art*_*sun 114
我想知道为什么没有人从MDN页面发布正确的解决方案 ......
const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};
JSON.stringify(circularReference, getCircularReplacer());
Run Code Online (Sandbox Code Playgroud)
看到的值应存储在一个集合中,而不是存储在数组中(每个元素都会调用replacer ),并且不需要尝试链中的JSON.stringify 每个元素,从而导致循环引用.
与接受的答案一样,此解决方案会删除所有重复值,而不仅仅是循环值.但至少它没有指数复杂性.
小智 66
做就是了
npm i --save circular-json
Run Code Online (Sandbox Code Playgroud)
然后在你的js文件中
const JSON = require('circular-json');
...
const json = JSON.stringify(obj);
Run Code Online (Sandbox Code Playgroud)
你也可以这样做
const CircularJSON = require('circular-json');
Run Code Online (Sandbox Code Playgroud)
https://github.com/WebReflection/circular-json
注意:我与此软件包无关.但我确实用它.
guy*_*abi 47
我真的很喜欢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);
};
Run Code Online (Sandbox Code Playgroud)
Ale*_*lls 37
@ RobW的回答是正确的,但这更高效!因为它使用hashmap/set:
const customStringify = function (v) {
const cache = new Set();
return JSON.stringify(v, function (key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.has(value)) {
// Circular reference found
try {
// If this value does not reference a parent it can be deduped
return JSON.parse(JSON.stringify(value));
}
catch (err) {
// discard key if value cannot be deduped
return;
}
}
// Store value in our set
cache.add(value);
}
return value;
});
};
Run Code Online (Sandbox Code Playgroud)
Nux*_*Nux 36
请注意,JSON.decycleDouglas Crockford 还实施了一种方法.看他的
cycle.js.这允许您对几乎任何标准结构进行字符串化:
var a = [];
a[0] = a;
a[1] = 123;
console.log(JSON.stringify(JSON.decycle(a)));
// result: '[{"$ref":"$"},123]'.
Run Code Online (Sandbox Code Playgroud)
您还可以使用retrocycle方法重新创建原始对象.因此,您不必从对象中删除循环以对其进行字符串化.
然而,这不适用于DOM节点(这是现实生活中使用情况下循环的典型原因).例如,这将抛出:
var a = [document.body];
console.log(JSON.stringify(JSON.decycle(a)));
Run Code Online (Sandbox Code Playgroud)
我已经做了一个分叉来解决这个问题(参见我的cycle.js fork).这应该工作正常:
var a = [document.body];
console.log(JSON.stringify(JSON.decycle(a, true)));
Run Code Online (Sandbox Code Playgroud)
请注意,在我的fork中JSON.decycle(variable)工作原样并且在variable包含DOM节点/元素时会抛出异常.
当你使用时,JSON.decycle(variable, true)你接受结果不可逆的事实(retrocycle不会重新创建DOM节点).但是DOM元素在某种程度上应该是可识别的.例如,如果div元素具有id,则它将被替换为字符串"div#id-of-the-element".
mik*_*eil 22
我建议从@isaacs中查看json-stringify- safe--它在NPM中使用.
安装:
$ npm install json-stringify-safe --save
Run Code Online (Sandbox Code Playgroud)
使用:
// 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));
Run Code Online (Sandbox Code Playgroud)
这会产生:
{
a: 'foo',
b: '[Circular]'
}
Run Code Online (Sandbox Code Playgroud)
请注意,就像提到的@Rob W的vanilla JSON.stringify函数一样,您也可以通过传入"replacer"函数作为第二个参数来自定义清理行为
stringify().如果你发现自己需要如何做一个简单的例子,我只是写了要挟的错误,正则表达式和功能为人类可读的字符串自定义替代品在这里.
Tri*_*daz 12
对于未来的googlers在您不知道所有循环引用的键时搜索此问题的解决方案,您可以使用JSON.stringify函数周围的包装来排除循环引用.请参阅https://gist.github.com/4653128上的示例脚本.
该解决方案基本上归结为保持对数组中先前打印的对象的引用,并在返回值之前在replacer函数中检查该对象.它比仅排除循环引用更加紧缩,因为它还排除了两次打印对象,其中一个副作用是避免循环引用.
包装示例:
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);
}
Run Code Online (Sandbox Code Playgroud)
var a={b:"b"};
a.a=a;
JSON.stringify(preventCircularJson(a));
Run Code Online (Sandbox Code Playgroud)
评估为:
"{"b":"b","a":"CIRCULAR_REFERENCE_REMOVED"}"
Run Code Online (Sandbox Code Playgroud)
具有以下功能:
/**
* 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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
670838 次 |
| 最近记录: |