我需要使用 ps 从 JSON 文件中提取一些信息。JSON 具有嵌套components
数组,其中也可以包含components
数组。
{
"name": "app",
"components": [
{
"component_name": "comp1",
"component_packages": [
"comp1_package1",
"comp1_package2"
],
"project_id": "1234",
"file_path": "requirements_file",
"ref": "%%VERSION%%",
"components": [
{
"component_name": "comp1.1",
"component_packages": [
"comp1.1_package1"
],
"project_id": "2345",
"file_path": "requirements_file",
"ref": "%%VERSION%%",
"components": [
{
"component_name": "comp1.1.1",
"component_packages": [
"comp1.1.1_package1"
],
"project_id": "3456",
"file_path": "requirements_file",
"ref": "%%VERSION%%",
"components": []
}]
},
{
"component_name": "comp1.2",
"component_packages": [
"comp1.2_package1"
],
"project_id": "4567",
"file_path": "requirements_file",
"ref": "%%VERSION%%",
"components": []
}
]
},
{
"component_name": "comp2",
"component_packages": [
"comp2_package1",
"comp2_package2"
],
"project_id": "5678",
"file_path": "requirements_file",
"ref": "%%VERSION%%",
"components": [
{
"component_name": "comp2.1",
"component_packages": [
"comp2.1_package1"
],
"project_id": "6789",
"file_path": "requirements_file",
"ref": "%%VERSION%%",
"components": []
}
]
}
]
}
对于每个component
内部,components
我需要执行一个脚本来收集更多信息,但我很难一一迭代所有元素。
我开始将 JSON 转换为 psobject ( Get-Content -Raw "$json_path" | ConvertFrom-Json
)
我不想修复 JSON 的深度。所以脚本应该具有适应性。
我尝试使用while
循环
$comp = $object.components
while ( $comp -ne "" ) {
$comp | ForEach-Object {
# to something
}
}
但这样它不适合,因为即使我覆盖$comp
,脚本也会忘记一些条目。
只需使用一个函数并递归调用它
(注意:这可能不是最有效的方法)
实际上不建议在 PowerShell 中提供不同的递归函数/脚本块调用方式来执行此操作,例如,如果 Json 太大,您会发现堆栈溢出问题。请参阅此处的两个答案。
推荐的方法是使用
Stack
orQueue
(或其通用对应物Stack<T>
andQueue<T>
)遍历 Json。如果涉及多个级别以及数组和哈希表的混合,处理对象图(独立于源,例如Json、Yaml或PowerShell本身)确实可能会变得相当复杂。这就是为什么我开始编写ObjectGraphTools模块,它可以帮助您探索相关对象、迭代节点或简单地查明特定节点(并更改其值)。
例子
列出该节点下的所有节点
$Object.components
:递归搜索所有
Components
节点(您的具体问题):但事情可能还没有结束。
要获取该节点下的叶节点的完整列表
$Object.components
:您可以使用特定路径属性来定位任何特定节点,例如:
或者使用Member-Access 枚举:
您可能要去的地方是获取
components
具有特定子节点的其中一个并更改另一个子节点的值。该语法还支持通配符,并具有一些扩展点表示法 (Xdn)运算符,可让您自由地定位深层节点。例如:
例如,更改具有of
ref
的值,例如:component
product_id
3456
(通过以下方式确认结果:
$Object | ConvertTo-Json -Depth 9
)解释:
~project_id
查找任何名为project_id的后代节点=3456
过滤结果节点,其中值等于3456..
选择父级ref
选择名为ref 的节点( project_id节点的同级)Value
是对对象图中相关值的引用,因此可以用于修改原始对象。