限制 JSON 字符串化深度

     2023-03-05     285

关键词:

【中文标题】限制 JSON 字符串化深度【英文标题】:Limit JSON stringification depth 【发布时间】:2013-05-04 04:35:30 【问题描述】:

当使用JSON.stringify(或类似的东西)对对象进行字符串化时,有一种方法可以限制字符串化深度,即只进入对象树的 n 层并忽略之后的所有内容(或者更好:在其中放置占位符,表示遗漏了某些内容)?

我知道JSON.stringify 采用function (key, value) 形式的替换函数,但我没有找到一种方法来获取传递给替换函数的当前键值对的原始对象的深度。

有没有办法使用默认的 JSON.stringify 实现来做到这一点?还是我已经到了应该自己实现字符串化的地步? 或者您可以推荐另一个具有此选项的字符串化库?

【问题讨论】:

看起来这个问题的已接受答案可能会有所帮助:***.com/questions/13861254/… @Strille 嗯,它确实包含一个实现我想要的。我接受它,这意味着默认实现是不可能的?我宁愿使用默认实现,因为我认为它更快,因为它是本机实现的。但是感谢您的指点! 不,我很确定默认实现无法满足您的要求。 【参考方案1】:

这是一个尊重内置 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://***.com/a/57193345/1236397 - 包括 TypeScript 版本)

更新:修复了空数组呈现为空对象的错误。

【讨论】:

为每个数组条目打印空白不是很好 不确定你的意思。它根本不会为数组打印空白,我只是再次检查。 想象“a”包含所有对象(而不是 12 和 2 以及一个对象)。如果“a”有 500 个这样的对象,您会看到打印出 500 个空括号(深度为 1)。信息量不大。 这是设计使然。数组元素的深度为 1,而不是它们包含的对象。由于原始值不被视为嵌套对象,因此包含在内。数组中的任何对象都不能在属性设置为 undefined 的情况下输出 - 这是您自己的自定义要求。如果您想要具有属性的对象,请增加您的深度级别以包含这些属性及其原始值。一切都按预期进行。 作为记录,C# 在使用 Newtonsoft.Json 时对空对象执行相同的操作。当有空对象时,它输出 。该库在序列化期间不支持深度限制,但如果支持,您很可能会得到相同的结果,或者为 null)。在 JS 中,如果需要,很容易检测空对象。如果您想要 null 代替,则将此 a?[]: 更改为此 a?[]:null【参考方案2】:

我想在不包含第三方库/太多代码的情况下在第一级对对象进行字符串化。

如果您也在寻找相同的内容,这里有一个快速的单线:

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));

【讨论】:

不能正确处理数组。 @JamesWilkins 数组将被转换为字符串,使其可读,超出深度限制。我更新了我的答案以显示 [object Array] 不将数组暴露到第二级,但保留了我的旧解决方案。我还解决了数字将被转换为字符串的问题,我根本不转换未定义的,所以它们将被忽略。尽管如此,应该事先将数组作为***对象传递。 对不起,我不够清楚。我的意思是我认为具有原始值的数组与字符串具有相同的级别,它们就像字符数组(字符串)。在我的书中(可以这么说)将数组转换为字符串或“对象数组”不是正确的值。 a: [1,2,3], b: 1, c: “123” 都是一层。 在 C、C++、C# 等其他语言中,您可以更容易地看到整数数组与字符数组没有太大区别。在这两种情况下,对象都不是。也就是说,JavaScript 数组恰好是一个对象,但我仍然认为它不应该被视为深度有限的对象。 @JamesWilkins 那么我的示例中obj.keyD 的预期输出是什么? "keyD":[12,"test123",,[object Object]]?得出一个合乎逻辑的完美解决方案并不容易,因为尽管如此,有些情况会导致问题。就像我从第一级开始的数组中有一个数组怎么办?我相信,一个最佳的解决方案不会成为一个单一的班轮。所以这只是针对序列化而不需要反序列化,稍后。在我的情况下,我想出了这个解决方案来存储一些对象以供以后检查。【参考方案3】:

对您的对象进行深度克隆(使用诸如 low-dash 之类的库),执行您想做的任何修剪,然后将其传递给 JSON.stringify。我不会尝试重新发明 JSON.stringify,那是在错误的地方努力。

[EDIT] 看起来有人已经按照你的建议做了:JSON.stringify deep objects

我不建议这样做,因为原生 JSON.stringify 总是会更快、更健壮

[EDIT]这里是一个似乎可以做你想做的事的库:http://philogb.github.io/jit/static/v20/Docs/files/Core/Core-js.html#$jit.json.prune

【讨论】:

你的意思是有限深度的克隆 是的,可以这样做,可能比复制和修剪更有效 你的意思是lodash

JSON字符串化一个集合

】JSON字符串化一个集合【英文标题】:JSONstringifyaSet【发布时间】:2015-09-2008:32:01【问题描述】:JSON.stringify()Set会怎样?在Chromium43中不起作用的地方:vars=newSet([\'foo\',\'bar\']);JSON.stringify(s);//->""JSON.stringify(s.values());//->""JSON.s... 查看详情

从 JSON 中提取深度嵌套的值

...ON【发布时间】:2021-08-0314:00:34【问题描述】:我想从JSON字符串中提取坐标并将它们分成2列,一列用于经度,一列用于纬度。这是位于event_location列中的示例JSON字符串:"type":"Feature","geometry":"type":"Point","coordinates":[-99.56 查看详情

java示例代码_读取具有可变数组深度和结构的复杂JSON字符串

java示例代码_读取具有可变数组深度和结构的复杂JSON字符串 查看详情

如何使用 SwiftyJSON 从深度嵌套的 JSON 字典中获取字符串 [重复]

】如何使用SwiftyJSON从深度嵌套的JSON字典中获取字符串[重复]【英文标题】:HowtogetstringfromdeeplynestedJSONdictionaryusingSwiftyJSON[duplicate]【发布时间】:2015-10-2316:57:43【问题描述】:提前致谢!我将如何从这个看起来像这样的JSON文件中... 查看详情

JSON 数组未正确字符串化

】JSON数组未正确字符串化【英文标题】:JSONarraydoesnotStringifyproperly【发布时间】:2019-01-1711:17:03【问题描述】:在我的Nodejs站点中,我创建了一个JSON数组并将其发送到angularJs客户端。然后它显示为[object,object]。由于这个原因,... 查看详情

在 Redshift 中解析 JSON 6 级深度

...ft中的JSON字段,但值是6级深。AWS说JSON_EXTRACT_PATH_TEXT有5级限制。我短暂地尝试了一个cte,但由于SQL和JSON对我来说是新的,所以我陷入了困境。或者,我想知道这样做的最佳位置是否在dbt中。如果是这样 查看详情

Json - 字符串化,使数组在一行上

】Json-字符串化,使数组在一行上【英文标题】:Json-stringifysothatarraysareononeline【发布时间】:2011-10-1918:05:09【问题描述】:是否可以将JSON对象字符串化为如下所示,数组在一行中-不缩进"Repeat":"Name":[["Top_level","All"],[[1,1]]],"Link":[... 查看详情

从深度嵌套的 JSON 创建 Pandas DataFrame

...014-02-2423:19:21【问题描述】:我正在尝试从深度嵌套的JSON字符串创建单个PandasDataFrame对象。JSON架构是:"intervals":[pivots:"JaneSmith","series":["interval_id":0,"p_va 查看详情

解析字符串化 JSON 字符串时出错

】解析字符串化JSON字符串时出错【英文标题】:ErrorparsingstringifiedJSONstring【发布时间】:2012-10-0404:13:16【问题描述】:假设我有一个对象:person=\'name\':\'john"Garfield"\';我把它转换成字符串:JSON.stringify(person);//RESULT:"name":"john\\"Garf... 查看详情

BigQuery 中未嵌套的 json 对象的字符串化数组

】BigQuery中未嵌套的json对象的字符串化数组【英文标题】:UnneststringifiedarrayofjsonobjectsinBigQuery【发布时间】:2019-07-1918:19:24【问题描述】:我有一个表,其中包含一个string列,其中包含一个JSON对象的字符串化列表,如下所示:\'... 查看详情

解决json字符长度超出限制

环境asp.net 4.0 ,AJAX一般处理程序碰到JSON字符长度超出限制,抛出异常,参考了网上资料和网友博客web.config添加以下内容<system.web.extensions> <scripting> <webServices> <jsonSerializationmaxJsonLength="2097152 查看详情

在 BigQuery 中取消嵌套 JSON 字符串化数组

】在BigQuery中取消嵌套JSON字符串化数组【英文标题】:UnnestaJSONstringifiedarrayinBigQuery【发布时间】:2020-07-2612:36:32【问题描述】:我在GoogleBigQuery中有下表:+------------+---------+---------+|Name|City|items|+------------+---------+|James|Dallas|[\'text... 查看详情

使用两组双引号取消嵌套字符串化 JSON

】使用两组双引号取消嵌套字符串化JSON【英文标题】:UnnestingstringifiedJSONwithtwosetsofdoublequotes【发布时间】:2021-11-1316:09:07【问题描述】:我有一个python脚本,它轮询API并将响应存储在BQ表中,该表具有如下所示的分层字符串化JS... 查看详情

java - 如何将字符串化的json对象转换回java中的json? [复制]

】java-如何将字符串化的json对象转换回java中的json?[复制]【英文标题】:Howtoconvertastringifiedjsonobjectbacktojsoninjava?[duplicate]【发布时间】:2021-10-2001:53:01【问题描述】:我有以下字符串值:\'["fruit":"apple","color":"green","fruit":"banana","c... 查看详情

将字符串化的 json 结构转换为 PHP 数组

】将字符串化的json结构转换为PHP数组【英文标题】:ConvertingastringifiedjsonstructuretoPHParray【发布时间】:2012-11-2908:33:22【问题描述】:我正在保存一个带有json数据的cookie。回显$_COOKIE[\'data\']示例[\\"date\\":1355249777,\\"title\\":\\"junior\\... 查看详情

在 AWS AppSync 中为 SQL 查询字符串化 JSON 对象

】在AWSAppSync中为SQL查询字符串化JSON对象【英文标题】:StringifyJSONobjectforSQLqueryinAWSAppSync【发布时间】:2020-10-1213:13:11【问题描述】:问题:如何在我的Appsync速度模板中为SQL语句字符串化JSON对象?说明:我有一个AuroraRDS表,其... 查看详情

JSON 字符串化到 C# Webservice

】JSON字符串化到C#Webservice【英文标题】:JSONstringifytoC#Webservice【发布时间】:2012-03-1803:17:01【问题描述】:我知道有一些问题,但我已经尝试了很多,但我什至无法将我的脚本发送到服务器。这是我目前拥有的:JavascriptfunctionUp... 查看详情

无法从 json 字符串实例化类型的值

】无法从json字符串实例化类型的值【英文标题】:Cannotinstantiatevalueoftypefromjsonstring【发布时间】:2014-09-1821:39:06【问题描述】:我在用户和组之间有双向多对多关系。@Entity@Table(name="UserTBL")publicclassUser@Id@SequenceGenerator(name="user_gen... 查看详情