iRon7 / Join-Object

Combines two objects lists based on a related property between them.
MIT License
107 stars 13 forks source link

How to reference nested objects? #8

Closed RobSederCVSH closed 4 years ago

RobSederCVSH commented 4 years ago

This is a truly amazing script - thank you for making it available. However, the samples include single-level documents, and all of that makes sense. I need to match on things that are further nested in. For example, I have something like this:

{
    "environments": [
        {
            "name": "dev",
            "servers": [
                {
                    "name": "SERVER1",
                    "app-pools": [
                        {
                            "name": "example1",
                            "account-id": "",
                            "identity-type": "ApplicationPoolIdentity",
                            "enabled": true
                        }
                    ],
                    "windows-services": [
                        {
                            "name": "mssqlserver",
                            "account-id": "service-account1",
                            "enabled": true
                        }
                    ],
                    "scheduled-tasks": [
                        {
                            "name": "some task",
                            "account-id": "service-account2",
                            "enabled": true
                        }
                    ]
                }
            ]
        },
        {
            "name": "qa",
            "servers": []
        },
        {
            "name": "prod",
            "servers": []
        }
    ]
}

After running a generation script for "sales web servers" and another "cms web servers" I have two similarly-structured documents. I want to merge the "dev" environment from BOTH files, keeping all of the unique properties. When there is a duplicate, I want to update the destination file and overwrite the old values. Basically an "add or update" kind of function.

It seems like I should do a $source | Merge-Object $destination -On environments as a start, but that just takes one side. I think the -On parameter needs to point environments[0].name or something like that merge on server name, but ANY kind of reference other that top-level references fails with, for example:

The property 'environments[0]' cannot be found on the left object.

Does this script support a way to merge on server name, in this case. That is, to merge on properties that are deeper into a complex object? Thanks very much

iRon7 commented 4 years ago

Thanks for the complement.

Unfortunately, you can't supply a sub property on the -On parameter.
Apart from the syntax for such a feature, I am afraid this might lead to confusion especially if there are also array indexes concerned...
Anyways, you might just join the embedded objects and inject that in the destination:

$Source = ConvertFrom-Json '{
    "environments": [
        {
            "name": "dev",
            "servers": [
                {
                    "name": "SERVER1",
                    "app-pools": [
                        {
                            "name": "example1",
                            "account-id": "",
                            "identity-type": "ApplicationPoolIdentity",
                            "enabled": true
                        }
                    ],
                    "windows-services": [
                        {
                            "name": "mssqlserver",
                            "account-id": "service-account1",
                            "enabled": true
                        }
                    ],
                    "scheduled-tasks": [
                        {
                            "name": "some task",
                            "account-id": "service-account2",
                            "enabled": true
                        }
                    ]
                }
            ]
        },
        {
            "name": "qa",
            "servers": []
        },
        {
            "name": "prod",
            "servers": []
        }
    ]
}'

$New = ConvertFrom-Json '{
    "environments": [
        {
            "name": "dev",
            "servers": [
                {
                    "name": "SERVER1",
                    "app-pools": [
                        {
                            "name": "exampleUPDATE",
                            "account-id": "",
                            "identity-type": "ApplicationPoolIdentity",
                            "enabled": false
                        }
                    ],
                    "windows-services": [
                        {
                            "name": "mssqlserver",
                            "account-id": "service-account1",
                            "enabled": true
                        }
                    ],
                    "scheduled-tasks": [
                        {
                            "name": "some task",
                            "account-id": "service-account1",
                            "enabled": true
                        }
                    ]
                },
                {
                    "name": "SERVER2",
                    "app-pools": [
                        {
                            "name": "exampleNEW",
                            "account-id": "",
                            "identity-type": "ApplicationPoolIdentity",
                            "enabled": true
                        }
                    ],
                    "windows-services": [
                        {
                            "name": "mssqlserver",
                            "account-id": "service-account2",
                            "enabled": true
                        }
                    ],
                    "scheduled-tasks": [
                        {
                            "name": "some task",
                            "account-id": "service-account2",
                            "enabled": true
                        }
                    ]
                }
            ]
        },
        {
            "name": "qa",
            "servers": []
        },
        {
            "name": "prod",
            "servers": []
        }
    ]
}'

$Destination = $Source
$Destination.environments[0].servers = `
    $Source.environments.servers | Merge $New.environments.servers -On Name
$Destination | ConvertTo-Json -Depth 9

    {
        "name": "SERVER1",
        "app-pools": {
            "name": "exampleUPDATE",
            "account-id": "",
            "identity-type": "ApplicationPoolIdentity",
            "enabled": false
        },
        "windows-services": {
            "name": "mssqlserver",
            "account-id": "service-account1",
            "enabled": true
        },
        "scheduled-tasks": {
            "name": "some task",
            "account-id": "service-account1",
            "enabled": true
        }
    },
    {
        "name": "SERVER2",
        "app-pools": {
            "name": "exampleNEW",
            "account-id": "",
            "identity-type": "ApplicationPoolIdentity",
            "enabled": true
        },
        "windows-services": {
            "name": "mssqlserver",
            "account-id": "service-account2",
            "enabled": true
        },
        "scheduled-tasks": {
            "name": "some task",
            "account-id": "service-account2",
            "enabled": true
        }
    }
]
RobSederCVSH commented 4 years ago

Oh - I hadn't even thought of that! Great idea, and thanks for the quick response and I appreciate you confirming the capabilities too, I appreciate it!