Search code examples
powershellpowershell-7.0

Powershell - Find and update all instances of named object property recursively


The problem

I need to use powershell to update all instances of a property called sourceList in a large exported JSON file, however the structure of the JSON is not consistent with each export, with the property occuring at various depths:

Example structure of JSON

{
    "rows": [
        {
            "controls": [
                {
                    "properties": {
                        "sourceList": "I NEED TO CHANGE THIS"
                    }
                }
            ]
        },
        {
            "controls": [
                {
                    "properties": {
                        "rows": [
                            {
                                "controls": [
                                    {
                                        "properties": {
                                            "sourceList": "ALSO THIS, BUT IT'S MUCH DEEPER"
                                        }
                                    }
                                ]
                            }
                        ]
                    }
                }
            ]
        }
    ]
}

The JSON file is from a form building tool, so different form designs (e.g. putting fields in group container) can cause the depth to change drastically.

Current Code

$formObj = Get-Content -Raw -Path $form | ConvertFrom-Json
# Find and update all instances of sourceList
$formObj | ConvertTo-Json -Depth 100 | Set-Content $form

The actual conversion to and from JSON works fine, and I've successfully changed some other properties that have a reliable structure, my issue is finding and updating a named property with no way of knowing at what depth it will occur.


Solution

  • Why not just do this...

    Select-String -Path '.\FormTool.txt' -Pattern 'sourceList' -Context 0
    # Results
    <#
    FormTool.txt:7:                        "sourceList": "I NEED TO CHANGE THIS"
    FormTool.txt:21:                                            "sourceList": "ALSO THIS, BUT IT'S MUCH DEEPER"
    #>
    

    Then modify at the line number or string match.

    (Select-String -Path '.\FormTool.txt' -Pattern 'sourceList' -Context 0) -replace '\:\s".*', ': "Repalced with this stuff"'
    # Results
    <#
    D:\Scripts\FormTool.txt:7:                        "sourceList": "Repalced with this stuff"
    D:\Scripts\FormTool.txt:21:                                            "sourceList": "Repalced with this stuff"
    #>