Search code examples
jsonpowershellobject-graph

Merging json objects in powershell


I have json that looks like this:

{
    "Workflow": [
        {
            "Parameters": {
                "Project": "/Path/To/File",
                "OtherParam": "True"
            }
        }
    ],
    "Overrides": [
        {
            "Special": {
                "Parameters": {
                    "NewParam": "NewStuffGoesHere",
                    "OtherParam": "False"
                }
            }
        }
    ]
}

... where I want to use the Overrides.Special section to add or update fields in the workflow object. In other words, given the json above, I want to do something like this:

$config = Get-Content workflow.json | out-string | ConvertFrom-Json
$configWithOverrides = Merge-Object $config.Workflow $config.Overrides.Special

And end up with something like this:

$configWithOverrides

Parameters
----------
@{Project=/Path/To/File; NewParam=NewStuffGoesHere; OtherParam=False}

I can certainly write the Merge-Object function above to add or update values as needed based on what's in the override section, but it seems there should (could?) be a built-in or one-liner way to handle this.

I tried this:

$test = $config.Workflow + $config.Overrides.Special

...but that doesn't quite work.

$test
Parameters
----------
@{Project=/Path/To/File; OtherParam=True}
@{NewParam=NewStuffGoesHere; OtherParam=False}

This enables adding parameters:

>$test.Parameters.NewParam
NewStuffGoesHere

...but it's not so great for updating them

>$test.Parameters.OtherParam
True
False

Note - in this example, I'm choosing to handle the merge after converting the json to a psobject, but that's not a requirement.


Solution

  • I have a one-liner to do what you're asking for. Notice that, as far as I know, PowerShell does not deal directly with json strings. But, once converted to PowerShell objects, it's like any other object.

    So, firstly, define your json file, and read it as a single string:

    # Requires -Version 4
    $jsonFile='c:\temp\jsonfile.json'
    $jsonObj=@(gc $jsonFile -raw)|ConvertFrom-Json
    

    Define the property upon which you want to merge the json's objects, and the 1st and 2nd objects:

    $property='Parameters'
    $1=$jsonObj.Workflow.$property
    $2=$jsonObj.Overrides.Special.$property
    

    Now, see the one-liner (which I've splitted in 3, for the sake of clarity):

    $MergedJson=[pscustomobject]@{
        $property=$2.psobject.properties|%{$11=$1}{$11|add-member $_.name   $_.value -ea Ignore}{$11}
    }|ConvertTo-Json
    

    You see? $MergedJson holds the following string (using your json string):

    {
        "Parameters":  {
                           "Project":  "/Path/To/File",
                           "OtherParam":  "True",
                           "NewParam":  "NewStuffGoesHere"
                       }
    }
    

    Is that what you're looking for?

    P.S.: if you swap the roles of $1 and $2, the common parameters' (like OtherParam) values that prevail, change.