I need to extract some informations from a json file using ps. The json has nested components
arrays wich can also contain a components
array.
{
"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": []
}
]
}
]
}
for each component
inside components
I need to execute a script to gather more information but I struggle with iterating to all the elements one by one.
I started to convert the json to a psobject (Get-Content -Raw "$json_path" | ConvertFrom-Json
)
I dont want to fix the depth of the json. So the script should be adaptable.
I tried using a while
loop
$comp = $object.components
while ( $comp -ne "" ) {
$comp | ForEach-Object {
# to something
}
}
but like this it is not suitable, because even if I overwrite $comp
, the script will forget some entries.
2
Answers
Just use a Function and call it recursively
(note: this might not be the most efficient way to do this)
Handling object-graphs (independent of the source, like Json, Yaml or PowerShell itself) might indeed become pretty complex if it concerns several levels and a mixture of arrays and hash tables. That’s why I started to write the ObjectGraphTools module which might help you to explore the concerned object, iterate through the nodes, or simply pinpoint a specific node (and change its value).
Examples
List all the nodes under the
$Object.components
node:Or get a full list of leaf nodes under the
$Object.components
node:You might target a specific node by using a specific path property, e.g.:
Or using Member-Access enumeration:
The syntax also supports wildcards and has some Extend Dot Notation (Xdn) operators which lets you freely target a deep node. E.g.:
To change the
ref
value of thecomponent
that has aproduct_id
of3456
, e.g.:(Confirm te results with:
$Object | ConvertTo-Json -Depth 9
)Explanation:
~project_id
finds any descendant node named project_id=3456
filters the resulted node where the value equals 3456..
selects the parentref
selects the node named ref (the sibling of the project_id node)Value
property of the node is a reference to the related value in the object-graph and might therefore might be used modify the original object.