I need to combine 2 json files with powershell that both have unique ID.
Json1
[
{
"id": "1",
"tags": {
"tag1": "value1",
"tag2": "value2"
}
},
{
"id": "2",
"tags": {
"tag1": "value1",
"tag2": "value2",
"tag3": "value3",
"tag4": "value4"
}
}
]
Json2
[
{
"ID": "1",
"Name": "name1",
"State": "Enabled"
},
{
"ID": "2",
"Name": "name2",
"State": "Disabled"
}
]
And the result should look like that:
[
{
"ID": "1",
"Name": "name1",
"State": "Enabled",
"tags": {
"tag1": "value1",
"tag2": "value2"
}
},
{
"ID": "2",
"Name": "name2",
"State": "Disabled",
"tags": {
"tag1": "value1",
"tag2": "value2",
"tag3": "value3",
"tag4": "value4"
}
}
]
Also it would be nice if new file could be converted to csv i tried ConvertTo-CSV but output was unusable.
Assuming you're only interested in matching pairs and both documents contain only objects with unique ID
values, the easiest way is to pick any of them and built an index table - either manually using a hashtable/dictionary, or by using Group-Object -AsHashtable
:
# create empty hashtable to store the objects from the tags documents
$tagStoreIndex = @{}
# read and parse json document, use Write-Output to enumerate the top-level array
Get-Content path\to\tags.json |ConvertFrom-Json |Write-Output |ForEach-Object {
# store object by ID
$tagStoreIndex[$_.ID] = $_
}
# alternatively use `Group-Object -AsHashTable` to construct the table
$tagStoreIndex = Get-Content path\to\tags.json |ConvertFrom-Json |Write-Output |Group-Object ID -AsHashTable
Now you can iterate over the objects in the second document and use the index table to quickly fetch the corresponding tags:
# read and parse second document
Get-Content path\to\states.json |ConvertFrom-Json |Write-Output |ForEach-Object {
if ($tagStoreIndex.ContainsKey($_.ID)) {
# construct new output object by attaching the tags from the other document
$_ |Select-Object *,@{Name='tags';Expression={$tagStoreIndex[$_.ID].tags |ConvertTo-Json -Compress}}
}
} |Export-Csv path\to\output.csv -NoTypeInformation
Using ConvertTo-Json
on the tags
object gives you a string value that you can later convert back to the original tags
object.
If you only need the tag values, change the property expression to
@{Name='tags';Expression={$tagStoreIndex[$_.ID].tags.psobject.Properties.Value -join ', '}}
If you want the tag names and values as bareword tokens, do:
If you only need the tag values, change the property expression to
@{Name='tags';Expression={$tagStoreIndex[$_.ID].tags.psobject.Properties.ForEach({$_.Name,$_.Value -join ':'}) -join ', '}}