代码之家  ›  专栏  ›  技术社区  ›  iRon

意外的转换为Json结果?回答:默认深度为2

  •  3
  • iRon  · 技术社区  · 6 年前

    为什么我会出人意料 ConvertTo-Json 结果,为什么我会得到这样的值 System.Collections.Hashtable 和/或为什么往返( $Json | ConvertFrom-Json | ConvertTo-Json )失败?

    元问题

    Stackoverflow有一个很好的机制来防止重复 问题 但据我所知,没有任何机制可以防止问题重复 原因 .以这个问题为例:几乎每周都会有一个新问题出现,原因相同,但通常很难将其定义为重复问题,因为问题本身略有不同。 尽管如此,如果这个问题/答案本身以重复(或离题)结尾,我也不会感到惊讶,但不幸的是,stackoverflow不可能 write an article 防止其他程序员继续编写由这个已知陷阱引起的问题。

    重复项

    具有相同共同原因的类似问题的几个示例:

    不同的

    那么,这个自我回答的问题是否与上述重复的问题不同?
    它在标题中有共同的原因,因此它可以更好地防止由于相同原因而重复提问。

    2 回复  |  直到 5 年前
        1
  •  32
  •   iRon    5 年前

    答复

    ConvertTo-Json 有一个 -Depth 参数:

    指定包含的对象在 JSON表示。
    这个 违约 值为 2.

    实例

    要使用JSON文件进行完整的往返,需要增加 -深度 对于 转换为Json cmdlet:

    $Json | ConvertFrom-Json | ConvertTo-Json -Depth 9
    

    TL;博士

    可能是因为 转换为Json 终止比默认值更深的分支 -深度 ( 2. )对于(.Net)完整类型名称,程序员假定存在bug或cmdlet限制,而不阅读帮助或关于。
    我个人认为 ellipsis (三点:)在截断分支的末尾,将有更明确的含义(另请参见:Github问题: 8381 )

    为什么?

    这个问题通常也会在另一个讨论中结束: 为什么深度是有限的?

    有些对象具有循环引用,这意味着如果子对象将被序列化为JSON,则子对象可能引用父对象(或其祖父母之一),从而导致不定式循环。

    以下面的哈希表为例 parent 引用对象本身的属性:

    $Test = @{Guid = New-Guid}
    $Test.Parent = $Test
    

    如果执行: $Test | ConvertTo-Json 默认情况下,它将在深度级别2处方便地停止:

    {
        "Guid":  "a274d017-5188-4d91-b960-023c06159dcc",
        "Parent":  {
                       "Guid":  "a274d017-5188-4d91-b960-023c06159dcc",
                       "Parent":  {
                                      "Guid":  "a274d017-5188-4d91-b960-023c06159dcc",
                                      "Parent":  "System.Collections.Hashtable"
                                  }
                   }
    }
    

    这就是为什么自动设置 -深度 大量的。

        2
  •  13
  •   mklement0    3 年前

    使现代化 : PowerShell 7.1引入了 警告 发生截断时 .虽然这比之前的好 轻声的 截断,下面建议的解决方案对我来说似乎更可取。


    您的有用问题和 answer 清楚地说明当前违约的痛处有多大 ConvertTo-Json 行为是。

    至于 正当理由 行为特征:

    虽然 -Depth 可用于 故意 截断不需要其全部深度的输入对象树, -深度 默认设置 2 悄悄地截断 输出总计 安静的实际故障 从毫无怀疑的用户的角度来看 -直到以后才能发现的故障。

    对大多数用户来说,这种看似任意且安静的截断是令人惊讶的,并且必须在每个 转换为Json 电话是不必要的负担。

    我已经创建了 GitHub issue #8393 包含 提议 更改当前行为,具体如下 :

    • 忽视 -深度 对于 [pscustomobject] 对象图(概念上是DTO(数据传输对象,“属性包”)的层次结构),例如从 Convert*From*-Json ),具体而言。

      • 相比之下 信息技术 对以下各项设置自动深度限制是有意义的 任意的网络类型 ,因为它们可能是深度过大的对象图,甚至可能包含循环引用;e、 g。, Get-ChildItem | ConvertTo-Json 可以快速失控 -深度 值低至 4 尽管如此, 使用武断的语言通常是不明智的。具有JSON序列化的NET类型 :JSON是 设计为给定平台类型的通用序列化格式;相反,它专注于DTO,包括 属性 仅限,带有 有限的数据类型集

      • 请注意,嵌套 集合 ,包括哈希表,其本身不受深度限制,仅受其(标量)的限制 元素

      • 事实上,DTO和其他类型之间的这种区别是PowerShell本身所采用的 幕后 ,即在序列化的上下文中 远程处理 后台作业

    • 使用 -深度 然后只需要 故意 在指定的深度截断输入对象树(或者,通常假设,为了序列化到比内部最大深度限制更深的级别, 100 )。

    推荐文章