Search code examples
jsonpowershellobject-graph

drill down to lowest JSON element using PowerShell


I need to extract some information from a JSON file using ps. The JSON has nested components arrays which 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 don't 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.


Solution

  • Just use a Function and call it recursively

    (note: this might not be the most efficient way to do this)

    $JsonObj = $Json | ConvertFrom-Json
    
    
    function Drill-Json {
        [CmdletBinding()]
        param (
            [Parameter(
                Mandatory,
                Position = 0,
                ValueFromPipeline,
                ValueFromPipelineByPropertyName,
                ValueFromRemainingArguments
            )]
            [array]$JsonComponent 
        )
            
        
        
        $JsonComponent | ForEach-Object {
            <# 
    
                DO STUFF
    
            #>
            # $_.component_name
            if (($_.components.count)) {
                Drill-Json -JsonComponent $_.components
            }
        
        }
    }
    
    Drill-Json -JsonComponent $JsonObj.components