意外的ConvertTo-Json结果?答:它的默认深度为2

时间:2018-12-02 19:13:54

标签: json powershell depth convertto-json

为什么我会得到意外的ConvertTo-Json结果?

元问题

Stackoverflow有一个很好的机制来防止重复的问题,但据我所知,还没有一种机制可以防止具有重复原因的问题。以这个问题为例:几乎每个星期都有一个新问题是由相同的原因引起的,但是通常很难将其定义为重复问题,因为问题本身只是稍有不同。 不过,如果这个问题/答案本身以重复(或脱题)结尾,我不会感到惊讶,但是不幸的是,stackoverflow无法write an article来防止其他程序员继续写由“已知”引起的问题。 ”陷阱。

重复

具有相同共同原因的类似问题的一些示例:

不同

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

2 个答案:

答案 0 :(得分:4)

答案

ConvertTo-Json具有 -Depth 参数:

  

指定包含在其中的对象的级别数   JSON表示形式。
  默认值为 2

TL; DR

可能是由于ConvertTo-Json终止了比默认-Depth 2 )更深的分支,并带有(.Net)完整类型名称,程序员可能会认为是错误或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"
                              }
               }
}

这就是为什么自动将-Depth设置为大量不是一个好主意的原因。

答案 1 :(得分:1)

您的问题清楚地说明了当前默认ConvertTo-Json行为带来的痛苦点。

关于行为的合理性

  

某些对象具有循环引用

在内部,ConvertTo-Json实际上具有防止无限深度序列化的安全功能:如果深度超过100级别,它将报告错误

此内部限制应该足够

虽然-Depth可以用于有意地截断不需要完整深度的输入对象树,但
-Depth 从毫无戒心的用户的角度来看,将默认设置为2悄悄地将输出等同于序列化的事实上的失败 -直到后来才发现的故障。

看似随意且安静的截断对于大多数用户来说是令人惊讶的,并且每次ConvertTo-Json调用中都要考虑它是不必要的负担。

我已创建this GitHub issue来请求更改当前行为,具体如下:

  • 删除-Depth的默认值

    • 100的硬编码内部限制(超过该限制时会报告错误),足以防止源于带有循环依赖关系的对象束的“失控” JSON字符串。
    • 典型情况下,典型的输入对象随后将被完全序列化。
  • 根据用户的判断,仅使用-Depth

    • 故意在指定深度截断输入对象树。
    • 在极少数情况下,允许序列化比100级更深的对象树。

如果您希望看到这种变化的发生(或不同意),请在此听到您的声音。