限制JSON字符串化深度
Limit JSON stringification depth
当使用JSON.stringify
(或类似的东西)字符串化对象时,是否有一种方法可以限制字符串化深度,即只进入对象树的n级别,忽略之后的所有内容(或者更好:在那里放置占位符,表明遗漏了某些内容)?
我知道JSON.stringify
采用function (key, value)
形式的替换函数,但我没有找到一种方法来获得当前键值对的原始对象的深度交给替换函数。
是否有办法做到这一点与默认JSON。stringify实现吗?或者我已经到了应该自己实现字符串化的地步了?或者您可以推荐其他具有此选项的字符串化库?
我想在不包含第三方库/太多代码的情况下在第一层对对象进行字符串化。
如果您要查找相同的内容,这里有一个快速的一行代码:
var json = JSON.stringify(obj, function (k, v) { return k && v && typeof v !== "number" ? (Array.isArray(v) ? "[object Array]" : "" + v) : v; });
顶层对象将没有键,所以它总是简单地返回,但是任何不是"数字"的下一层对象将被强制转换为字符串,包括数组的特殊情况,否则这些将被进一步暴露。
如果你不喜欢这种特殊的数组情况,请使用我以前的解决方案,我也改进了:
var json = JSON.stringify(obj, function (k, v) { return k && v && typeof v !== "number" ? "" + v : v; }); // will expose arrays as strings.
在顶层传递数组而不是对象在两种解决方案中都有效。
例子:
var obj = {
keyA: "test",
keyB: undefined,
keyC: 42,
keyD: [12, "test123", undefined]
}
obj.keyD.push(obj);
obj.keyE = obj;
var arr = [12, "test123", undefined];
arr.push(arr);
var f = function (k, v) { return k && v && typeof v !== "number" ? (Array.isArray(v) ? "[object Array]" : "" + v) : v; };
var f2 = function (k, v) { return k && v && typeof v !== "number" ? "" + v : v; };
console.log("object:", JSON.stringify(obj, f));
console.log("array:", JSON.stringify(arr, f));
console.log("");
console.log("with array string cast, so the array gets exposed:");
console.log("object:", JSON.stringify(obj, f2));
console.log("array:", JSON.stringify(arr, f2));
这是一个尊重内置JSON.stringify()
规则的函数,同时也限制了深度:
function stringify(val, depth, replacer, space) {
depth = isNaN(+depth) ? 1 : depth;
function _build(key, val, depth, o, a) { // (JSON.stringify() has it's own rules, which we respect here by using it for property iteration)
return !val || typeof val != 'object' ? val : (a=Array.isArray(val), JSON.stringify(val, function(k,v){ if (a || depth > 0) { if (replacer) v=replacer(k,v); if (!k) return (a=Array.isArray(v),val=v); !o && (o=a?[]:{}); o[k] = _build(k, v, a?depth:depth-1); } }), o||(a?[]:{}));
}
return JSON.stringify(_build('', val, depth), null, space);
}
工作原理:
- 递归调用
-
_build()
来构建嵌套的对象和数组到请求的深度。JSON.stringify()
用于迭代每个对象的直接属性,以遵守内置规则。'undefined'总是从内部替换器返回,所以实际上还没有构建JSON。请记住,第一次调用内部替换器时,键是空的(这是要字符串化的项)。 -
JSON.stringify()
在最终结果时被调用以产生实际的JSON。
的例子:
var value={a:[12,2,{y:3,z:{q:1}}],s:'!',o:{x:1,o2:{y:1}}};
console.log(stringify(value, 0, null, 2));
console.log(stringify(value, 1, null, 2));
console.log(stringify(value, 2, null, 2));
{}
{
"a": [
12,
2,
{}
],
"s": "!",
"o": {}
}
{
"a": [
12,
2,
{
"y": 3,
"z": {}
}
],
"s": "!",
"o": {
"x": 1,
"o2": {}
}
}
(对于处理循环引用的版本,见这里:https://stackoverflow.com/a/57193345/1236397 -包含TypeScript版本)
更新:修复了一个空数组呈现为空对象的错误。
创建对象的深度克隆(使用lodash之类的库),执行您想要执行的修剪操作,然后将其传递给JSON.stringify。我不会尝试重新发明JSON。Stringify,就是把精力放在了错误的地方。
[EDIT]看起来有人已经做了你所建议的:JSON。字符串化深度对象
我不推荐这样做,因为原生JSON。Stringify总是会更快更健壮
[EDIT]这里是一个库,似乎做你想要的:http://philogb.github.io/jit/static/v20/Docs/files/Core/Core-js.html#$jit.json.prune
- 如何在JavaScript中将字符串转换为函数引用
- jQuery中是否内置了任何字符串格式化函数
- Javascript,有没有一种方法可以将数组写成没有逗号或空格的单个文本字符串
- ng打开空字符串
- 正则表达式在字符串中找到base64
- 如何将字符串值从php页面发送到java脚本页面
- 子字符串/正则表达式以获取字符串中保存的 SRC 值
- 字符串在将其传递给另一个活动Android JavaScript时读取Null
- 对id以某个字符串开头的元素进行计数
- Javascript逻辑运算符和字符串/数字
- 反向字符串比较
- 如何有效地将游戏数据存储在URL查询字符串中
- 可变大小的JavaScript字符串如何成为基元类型
- Javascript 深度对象相等时,对象通过 json 字符串与生成器创建
- 下划线.js :深度嵌套对象中的匹配字符串
- 如何做一个深度搜索对象从一个给定的字符串
- 限制JSON字符串化深度
- 用于匹配有限深度嵌套字符串的正则表达式——缓慢、崩溃的行为
- 如何使用分隔字符串在任意深度定位和修改对象键
- 限制给定 html 字符串上的标记深度