3

I have two JSON objects and I am trying to build one object out of it. I am using an example here, but the properties/names are dynamic.

I have looked into JOIN function, MERGE, Combine-Object none of them seems to do what I want. As they either replace the values with the one or give me random results.

This is my example,

$aVar = '{ "oldEmployees" : [ { "firstName": "Jane", "lastName": "Doe" }, { "firstName": "John", "lastName": "Doe" } ] }'
$bVar = '{ "newEmployees" : [ { "firstName": "Joe", "lastName": "Doe" } ] }'

I would like to have one JSON as,

{
    "oldEmployees": [
        {
            "firstName": "Jane",
            "lastName": "Doe"
        }, 
        {
            "firstName": "John",
            "lastName": "Doe"
        }
    ],
    "newEmployees": [
        {
            "firstName": "Joe",
            "lastName": "Doe"
        }
    ]
}

BACKGROUND: I am using a JSON object to deploy multiple resources in Azure DevOps pipeline using an ARM template. I have hit a point where I am limited to use Powershell script to combine multiple variables due to the size limit on the Azure Pipeline Variables to a max of 4K characters.

PEF
  • 125
  • 2
  • 11
  • Is there a reason you are using Powershell to do this – Panomosh Aug 30 '19 at 10:29
  • Yes, I have to add it in my Azure pipelines and my options are restricted to Powershell script. – PEF Aug 30 '19 at 10:30
  • I don't know what went wrong (maybe an older version) but the [Join-Object](https://stackoverflow.com/a/45483110/1701026) cmdlet, you refer to, gives exactly the results that you would like to have: `($aVar | ConvertFrom-Json) |` [`Join-Object`](https://www.powershellgallery.com/packages/Join) `($bVar | ConvertFrom-Json) | ConvertTo-Json -Compress` → `{"oldEmployees":[{"firstName":"Jane","lastName":"Doe"},{"firstName":"John","lastName":"Doe"}],"newEmployees":{"firstName":"Joe","lastName":"Doe"}}` (See also: [Merge two json objects](https://stackoverflow.com/q/45549909/1701026)) – iRon Nov 18 '19 at 09:46

3 Answers3

4

Simply pipe your definition to |Convertfrom-Json

$aVar = '{ "oldEmployees" : [ { "firstName": "Jane", "lastName": "Doe" }, { "firstName": "John", "lastName": "Doe" } ] }' |ConvertFrom-Json
$bVar = '{ "newEmployees" : [ { "firstName": "Joe", "lastName": "Doe" } ] }'|ConvertFrom-Json

$aVar,$bVar|ConvertTo-Json

The result is ugly formatted with PSv5 it get's better with core.

[
    {
        "oldEmployees":  [
                             "@{firstName=Jane; lastName=Doe}",
                             "@{firstName=John; lastName=Doe}"
                         ]
    },
    {
        "newEmployees":  [
                             "@{firstName=Joe; lastName=Doe}"
                         ]
    }
]
  • This is insanely simple. I probably just thought is something more complicated. But it is simple if you know what you are doing. Really appreciate it. :) – PEF Aug 30 '19 at 10:53
  • I actually did not know you could chain variables like that `$aVar,$bVar` thanks @LotPings – Panomosh Aug 30 '19 at 10:54
  • 1
    Note that this still produces an array in the output JSON – JamesQMurphy Aug 30 '19 at 10:57
4

This will give you the exact JSON that you seek:

$combinedObject = New-Object -TypeName PSObject -Property @{
    oldEmployees = @($aVar | ConvertFrom-Json | Select-Object -ExpandProperty oldEmployees)
    newEmployees = @($bVar | ConvertFrom-Json | Select-Object -ExpandProperty newEmployees)
} | ConvertTo-Json

It's the same approach as Panomosh's answer, except that instead of using an array, I used a property map. This prevents the output from having an array.

JamesQMurphy
  • 4,214
  • 1
  • 36
  • 41
  • very nice @JamesQMurphy – Panomosh Aug 30 '19 at 10:55
  • This is great. Thank you so much! – PEF Aug 30 '19 at 11:03
  • @JamesQMurphy Okay, the only issue I have with this is, I am not getting $bVar as an array anymore. The output I have is `{ "oldEmployees": [ { "firstName": "Jane", "lastName": "Doe" }, { "firstName": "John", "lastName": "Doe" } ], "newEmployees": { "firstName": "Joe", "lastName": "Doe" } }`. Where I want it to be `{ "oldEmployees": [ { "firstName": "Jane", "lastName": "Doe" }, { "firstName": "John", "lastName": "Doe" } ], "newEmployees": ** [**{ "firstName": "Joe", "lastName": "Doe" }**]** }`. Even though there is only one employee in it. – PEF Aug 30 '19 at 11:13
  • Think it doesn't matter. But wanted to see it consistent. If not, it is okay. I believe it should work. Will keep you posted. – PEF Aug 30 '19 at 11:19
  • 1
    I have updated my answer so that `oldEmployees` and `newEmployees` are always arrays – JamesQMurphy Aug 30 '19 at 11:52
3

you are going to have to turn both of the JSON into powershell objects, combine them, and then turn them back into JSON. In the example above, powershell will just see them as strings.

You can do this like so:

$container = @()
$container += ConvertFrom-Json '{ "oldEmployees" : [ { "firstName": "Jane", "lastName": "Doe" }, { "firstName": "John", "lastName": "Doe" } ] }'
$container += ConvertFrom-Json '{ "newEmployees" : [ { "firstName": "Joe", "lastName": "Doe" } ] }'

$combinedObject = $container | ConvertTo-Json

now if you view $combinedObject you will see:

[
{
    "newEmployees":  [
                         "@{firstName=Joe; lastName=Doe}"
                     ]
},
{
    "oldEmployees":  [
                         "@{firstName=Jane; lastName=Doe}",
                         "@{firstName=John; lastName=Doe}"
                     ]
}
]
Panomosh
  • 884
  • 2
  • 8
  • 18