PowerShell 的 ConvertTo-Json 导致嵌套消失?更改 Depth 观察结构

PowerShellカテゴリを表すパンダのイラスト PowerShell

关于本文
本文是通过利用生成式 AI 的自动化生成流程创建的。基于 Microsoft Learn 中关于 ConvertTo-Json 和 ConvertFrom-Json 的规范,整理了使用虚拟设备数据的复现步骤与判断方法。

验证状态:📘 已参考官方规范,未在 PowerShell 实机上进行操作

PowerShell 的 ConvertTo-Json 导致嵌套消失?更改 Depth 观察结构

在 PowerShell 中创建 JSON 时,虽然屏幕上会显示部门名称和负责人,但将保存的 JSON 传递给其他系统时,中间的信息有时会变成字符串。特别是在组装配置文件或发送到 API 的数据时,仅凭外观判断其是否正常是危险的。原因之一就是ConvertTo-Json 中的 -Depth。本次不调用外部服务,通过内存中的虚拟数据来观察层级与转换结果的关系。

首先会发生什么

例如,设想总务部门制作设备管理的 JSON 并移交给其他负责人的场景。不仅是设备名称,还希望将管理部门及其部门的联系方式汇总到一个数据中。在 PowerShell 中,通过嵌套哈希表可以自然地表现出来。但是,转换为 JSON 时的深度限制是与 PowerShell 上的数据结构深度分开指定的。转换后的 JSON 在语法上是否正确与所需属性是否保留也是两个不同的问题。

这里想要确认的是,Depth 改变时,仅仅是字符数增加,还是对象本身的结构发生了变化。请在做出预测后对比两个结果。执行的代码预计为 PowerShell 7 系列的简短代码,不需要管理员权限或网络连接。

安全实验:将相同的数据转换两次

打开 PowerShell 7 并将以下内容作为一个代码块执行。请勿填入业务中的真实联系方式或 API 令牌,姓名和电话号码均使用纯虚拟信息。该代码不会创建文件,仅向屏幕输出字符串。

$item = @{
    item = '架空ノートPC'
    owner = @{
        department = '総務'
        contact = @{
            name = '担当A'
            extension = '0000'
        }
    }
}

'=== depth 2 ==='
$item | ConvertTo-Json -Depth 2
'=== depth 5 ==='
$item | ConvertTo-Json -Depth 5

需要关注的是,owner 内部的 contact 是否会作为 JSON 对象保留。默认深度为 2。在深度不足的地方,原始对象可能不会表现为期望的嵌套 JSON,而是被转换为字符串。在 PowerShell 7.1 及更高版本中,也有超过指定深度时发出警告的规范。请观察不仅有无警告,还有转换结果的引号和大括号。

-Depth 5 设置为指定值的那一方,预计这次较小的嵌套将被表现为 JSON 对象。但是,发布的内容是根据规范推导出的预期行为,并非在制作本文时通过在 Windows 上运行 PowerShell 获得の実测日志。执行后,请将两边的输出并排对照,contact 后面是否紧跟大括号,或者确认它是否变成了带单引号的字符串。

图解:数据与JSON化的边界

下图展示了在将PowerShell的嵌套结构转换为JSON时,深度参数是如何生效的。即使左侧的数据相同,如果转换条件不同,输出的结构也会发生变化。图中的分支仅用于便于理解的概念图,并不断定PowerShell内部实现的函数调用顺序。

flowchart TD
    A["入れ子のPowerShellオブジェクト"] --> B["ConvertTo-Json"]
    B --> C{"Depthは十分か"}
    C -->|はい| D["入れ子をJSONオブジェクトとして表現"]
    C -->|いいえ| E["深い部分が期待どおりの構造にならない"]
    D --> F["受け手がキーをたどれる"]
    E --> G["構造を確認しDepthを見直す"]

这张图的重要之处在于,即使JSON语法检查成功,右侧的接收方也不一定能顺着预期的键找到数据。例如owner.contact.name在假设以下层级的处理中,contact如果变成了一个字符串,其下方的name这个键就无法被取出了。这就是为什么在怀疑发送端故障之前,需要先检查发送前JSON的原因。

更进一步:从JSON还原并确认结构

仅凭肉眼观察屏幕上的字符串,有时会漏掉引号或转义符。如果将转换结果再次转换回PowerShell对象,并确认目标值究竟是字符串还是带属性的对象,就会更容易做出判断。在接下来的示例中,将重新加载指定了足够深度的JSON,并获取负责人姓名。

$json = $item | ConvertTo-Json -Depth 5
$restored = $json | ConvertFrom-Json
$restored.owner.contact.name
$restored.owner.contact.GetType().FullName

期望的负责人姓名是担当A。由于类型名称的显示取决于运行环境和转换后的对象表示形式,因此不会将固定字符串作为通过条件。重要的是,contact不是一个单纯的字符串,而是能够恢复为可以引用name的结构。即使$restored.owner.contact.name变空了,也不要立即断定整个JSON就是空的。应当先检查原始JSON中该位置到底是对象还是字符串。

ConvertFrom-Json是用于读取JSON内容的解析处理,它并非旨在完美恢复原始PowerShell对象类型和细微性质的通用序列化程序。在这里,它被用作一种工具,用来检查从JSON接收方的角度来看键的层级是否得到了维护。这需要与旨在实现与原始类型完全一致的测试区分开来考虑。

只改动一个条件:增加Depth能带来什么改善

只需将最初代码中的-Depth 2修改为-Depth 5。不改变输入数据、PowerShell版本以及转换目标。这样更容易认为输出的差异是由深度指定引起的。不要仅以转换结果变长作为成功条件,而是要确认owner、contact、name这三个层级是否可以作为JSON的键进行追踪。

另一方面,盲目指定一个非常大的数字也并不意味着万事大吉。随着深度的增加,原本无意包含的内部数据也可能会成为输出对象。如果是用于API发送的JSON,显式地将所需的键构建到新的哈希表中,有时会比直接转换整个输入对象更加安全。请计算所需的层级,并设置符合预期架构的值。

从这次对比中可以明白,Depth并不是“在屏幕上显示多少行”的设置,而是决定在转换时处理到哪一层嵌套的设置。即便转换前的 PowerShell 值正确,在决定输出格式的阶段信息的形态也可能会发生变化。在数据集成出现故障时,调查输入与输出之间的转换条件的视角会非常有用。

发生失败时的排查

首先想确认的是,究竟是 PowerShell 本身输出了错误,还是虽然生成了 JSON 但并非预期的结构。如果是前者,则记录错误信息和版本。如果是后者,则提取 JSON 的目标部分,检查引号和大括号。由于两者的原因不一定相同,因此切勿将应对方法混为一谈。

接下来,确认实际指定的-Depth的值以及 PowerShell 的版本。如果一直依赖默认值,请将其改为显式指定并比较差异。关于 PowerShell 7.1 及更高版本的警告,请不要将看不见显示视为“深度足够的证据”。由于它受警告处理方式和主机显示方法的影响,直接检查输出结构会更可靠。

如果仍然无法达到预期,请检查原始数据中是否存在同名字段,是否混入了$null,或者是否弄混了数组和单一对象。如果将即使改变深度也无法修复的故障全都归咎于Depth,就会忽视其他问题。最稳妥的做法是,只保留目标的最小数据,并在去除不需要的属性的状态下确认是否能够重现问题。

此外,仅确认 JSON 语法正确是不够的。还必须核对接收方所需的键、值的类型、是数组还是对象等形态。JSON 不仅仅是字符串,更是用于传递数据结构的格式。不仅要看懂数值,接收方能否通过预期的路径访问到该数值,才是实际业务中的合格标准。

在业务中运用时的判断

例如,在将 JSON 发送到 Microsoft Graph 等 API 的处理中,在追查目标服务器的错误之前,先确认本地创建的请求正文的形态。不过,由于每个 API 所需的必需键和类型各不相同,这并不意味着本示例可以直接用于 API。应优先考虑符合 API 规范的专用数据结构,并设计为只转换必要的层级。

输出配置文件时也是如此。首先用虚拟数据输出,重新读取 JSON 以确认所需的层级依然保留。之后再应用于实际数据。切勿将包含机密数据的数据直接显示在屏幕或日志中。要确保用于调查的 JSON 显示不会反过来导致认证信息或个人信息的泄露。

如果要将处理自动化,则在转换后检查是否存在必需的键,然后再进行下一步。关键在于不要仅凭“成功创建了 JSON”就判定为正常结束,而是要检查所需的结构。如果缺少预期的键,则应中止发送或覆盖,并重新审视示例的层级和转换条件。没有必要使用此学习代码来执行实际文件的替换或对 API 的 POST 操作。

最后要记住的是,将问题所在分为三部分:PowerShell 的原始数据是否正确,JSON 转换是否保持了形态,是否符合接收方的规范。按顺序检查这些内容,就能从单纯盲目增大-Depth的临时对策,进阶到可重现的数据集成验证。

总结

ConvertTo-Json中的-Depth不仅是用于美化 JSON 外观的选项,更是保持嵌套结构的重要设置。用相同的虚拟数据改变一次深度,并通过ConvertFrom-Json重新读取输出的 JSON,便可确认是否能够访问接收方期望的键。分项检查深度指定、输出结构和目标架构,是减少实际业务中失误的捷径。

官方文档与第一手资料

  • Microsoft Learn — ConvertTo-Json: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertto-json

  • Microsoft Learn — ConvertFrom-Json: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-json

文档信息

文章??
PowerShell 的 ConvertTo-Json 导致嵌套消失?更改 Depth 观察结构
?布日期
更新日期
来源
https://papanda925.com/?p=18565&lang=zh

?可: ?于本站?有相??利的正文及原??表,除非?有?明,可依据 CC BY 4.0 使用。本文可能包含使用生成式AI?建或??的内容。若代??有?可声明,或?接的GitHub???定了?可,?代?以??可?准。引用内容、第三方?料、?片及商?不在本?可范?内。 使用政策

标题和URL已复制