Append Members to an Array in JSON with PowerShell - json

I need to use Powershell to insert data into a json file within an array. Here is the json original structure
{
"Array": [
{
"servername": "foo"
},
{
"servername": "boo"
}
]
}
Here is the new structure:
{
"Array": [
{
"servername": "Foo",
"Disk": "100"
},
{
"servername": "Boo",
"Disk": "500"
}
]
}
Why does this not work?
$json = #"
{
"Array": [
{
"servername": "Foo"
},
{
"servername": "Boo"
}
]
}
"#
$jsonServerFoo=#"
{
"Disk": "100"
}
"#
$jsonServerBoo=#"
{
"Disk": "500"
}
"#
$jsonObj = $JSON | ConvertFrom-Json
$jsonServerFooObj = $jsonServerFoo | ConvertFrom-Json
$jsonServerBooObj = $jsonServerBoo | ConvertFrom-Json
$i = 1
$jsonObj.Array | Foreach-object {
if ( $i -eq 1 ) {
$_ | Add-Member -MemberType NoteProperty -Name "Disk" -Value $jsonServerFooObj.Disk
$i++
}
else {
$_ | Add-Member -MemberType NoteProperty -Name "Disk" -Value $jsonServerBooObj.Disk
}
}
$jsonObj
$jsonObj | ConvertTo-Json -Depth 100
I get the desired output
{
"Array": [
{
"servername": "Foo",
"Disk": "100"
},
{
"servername": "Boo",
"Disk": "500"
}
]
}

Use Add-Member to add members to a PSCustomObject. ConvertFrom-Json returns a PSCustomObject, not a Hashtable.
$jsonObj | Add-Member -MemberType NoteProperty -MemberName MyPropertyName -Value "some value, doesn't have to be a string"
You don't have to work with the base $jsonObj either, you can also add members to nested members of $jsonObj as well. In your case, with the Array member:
$jsonObj.Array | Foreach-object {
if( $i -eq 1 ) {
$_ | Add-Member -MemberType NoteProperty -Name Disk -Value $jsonServerFooObj.Disk
$i++
} else {
$_ | Add-Member -MemberType NoteProperty -Name Disk -Value $jsonServerBooObj.Disk
}
}
You may also want to consider calling ConvertTo-Json -Depth 100 so you don't get the default object depth which is low, 3 I think.
As noted by #user2864740, in PowerShell 6 ConvertFrom-Json has the -AsHashtable parameter if you would rather work with a Hashtable than a PSCustomObject.

Related

Powershell - Remove from Json

I have the following Json file:
{
"Id":1,
"Name":"john",
"Addresses":[
{
"Id":1,
"Street":"1st Street",
"City":"Riyadh"
},
{
"Id":2,
"Street":"2nd Street",
"City":"Dammam"
}
]
}
I want to remove the second address in the array using powershell.
I tried the following:
$filePath = 'C:\temp\Settings.json'
$settings = $filePath | ConvertFrom-Json
foreach($item in $settings.Addresses)
{
if($item.Id -eq 2)
{
$settings.Addresses.Remove($item)
}
}
Any ideas?
The following commented code snippet could help:
$filePath = 'C:\temp\Settings.json'
$settings = Get-Content -Path $filePath | ConvertFrom-Json
# $settings.Addresses # is an array of fixed size
# $settings.Addresses.IsFixedSize # returns True
# $settings.Addresses.Remove($item) # isn't possible; hence, let's build new array:
$NewAddresses = [System.Collections.ArrayList]::new()
foreach($item in $settings.Addresses)
{
if ($item.Id -ne 2)
{
[void]$NewAddresses.Add( $item )
}
}
# and replace old one:
$settings.Addresses = $NewAddresses
$settings | ConvertTo-Json ### | Out-File -FilePath $filePath -Force -Encoding utf8
Output: .\SO\66855002.ps1
{
"Id": 1,
"Name": "john",
"Addresses": [
{
"Id": 1,
"Street": "1st Street",
"City": "Riyadh"
}
]
}

How to add a value and key into existing JSON file over powershell?

I would like to add an additional key with value into my existing JSON file. Unfortunately I'm not able. Here an short overview:
My JSON-File before powershell script is run:
[
{
"id": "1",
"description": [
{
"country": "Brazil"
},
{
"country": "Mexico"
}
]
},
{
"id": "2",
"description": [
{
"country": "Argentina"
}
]
}
]
My wish, how the JSON-File should look like, after my powershell script is run:
[
{
"id": "1",
"description": [
{
"country": "Brazil",
"city": "Rio de Janeiro"
},
{
"country": "Mexico",
"city": "Mexico City"
}
]
},
{
"id": "2",
"description": [
{
"country": "Argentina",
"city": "Buenos Aires"
}
]
}
]
My powershell script:
function GetCity($country) {
$x = "not available"
If ( $country -eq "Brazil" ) { $x = "Rio de Janeiro" }
If ( $country -eq "Mexico" ) { $x = "Mexico City" }
If ( $country -eq "Argentina" ) { $x = "Buenos Aires" }
return $x
}
# Source the JSON content
$jsonFile = 'C:\Temp\test.json'
$jsonContent = Get-Content -Path $jsonFile
# Convert JSON to PSObjects
$jsonAsPsObjects = $jsonContent | ConvertFrom-Json
foreach ($info in $jsonAsPsObjects) {
$result = GetCity($info.description.country)
jsonContent | Add-Member -Type NoteProperty -Name "City" -Value $result
}
# Save JSON back to file
$json | ConvertTo-Json | Set-Content $jsonFile
Error:
jsonContent : The term 'jsonContent' is not recognized as the name of
a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path
is correct and try again.
How can I solve this issue?
There at two problems:
jsonContent should be $jsonContent in statement jsonContent | Add-Member ...
You're neglecting to loop over the array elements of the description property, to each of which a city property is to be added.
I suggest streamlining your code as follows:
function Get-City {
param([string] $country)
# Use a `switch` statement:
switch ($country) {
'Brazil' { return 'Rio de Janeiro' }
'Mexico' { return 'Mexico City' }
'Argentina' { return 'Buenos Aires' }
default { return 'not available' }
}
}
$jsonFile = 'C:\Temp\test.json'
(Get-Content -Raw $jsonFile | ConvertFrom-Json) | ForEach-Object {
# Add a 'city' property to each object in the 'description' property.
$_.description.ForEach({
Add-Member -InputObject $_ city (Get-City $_.country)
})
$_ # output the modified object
} | ConvertTo-Json -Depth 3 # | Set-Content $jsonFile

Powershell for JSON

I made this script in powershell to collect some information from the computer and I need to export to JSON format with some specifications
$osinfo = Get-WmiObject Win32_OperatingSystem -ErrorAction STOP |
Select-Object #{Name='computername';Expression={$_.CSName}};
Write-Host "Computer_INfo:"
$osinfo | ConvertTo-Json
$rede = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ErrorAction STOP | where-object -FilterScript {$_.IPEnabled -eq $true} | Select-Object #{Name='Description';Expression={$_.Description}},
#{Name='IP_Address';Expression={$_.IPAddress[0]}};
Write-Host "LAN_INfo:"
$rede | ConvertTo-Json
The result of this command generates this JSON
Computer_INfo:
{
"computername": "DESKTOP-PCJTTEG"
}
LAN_INfo:
[
{
"Description": "Hyper-V Virtual Ethernet Adapter",
"IP_Address": "192.168.65.241"
},
{
"Description": "Hyper-V Virtual Ethernet Adapter #2",
"IP_Address": "192.168.10.104"
}
]
I wanted it to be this way.
{Computer_Info:
[
{
"computername": "DESKTOP-PCJTTEG"
}
]
},LAN_INfo:{
[
{
"Description": "Hyper-V Virtual Ethernet Adapter",
"IP_Address": "192.168.65.241"
},
{
"Description": "Hyper-V Virtual Ethernet Adapter #2",
"IP_Address": "192.168.10.104" }
]
}
You can define the structure for your Json by designing your PSCustomObject in the way you desire. To have arrays, even if you have 1 element, add the #() array constructor. When converted to json, il will transpose to your missing []
Default depth when converting to Json is 4, which can be adjusted up to 100 layers.
In the case of your output, I adjusted it to avoid missing some content in the final output.
Here's your code, with the rendered output you were looking for.
$osinfo = Get-WmiObject Win32_OperatingSystem -ErrorAction STOP |
Select-Object #{Name = 'computername'; Expression = { $_.CSName } };
$rede = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ErrorAction STOP | where-object -FilterScript { $_.IPEnabled -eq $true } |
Select-Object #{Name = 'Description'; Expression = { $_.Description } },
#{Name = 'IP_Address'; Expression = { $_.IPAddress[0] } };
[PSCustomObject]#{
Computer_Info = #(
$osinfo,
#{'LAN_INfo' = $rede }
)
} | ConvertTo-Json -Depth 10

Json to CSV in Powershell

I'm working with Powershell, querying Azure Log analytics with the LogAnalyticsQuery module using Invoke-LogAnalyticsQuery.
I have the results
{
"tables": [
{
"name": "PrimaryResult",
"columns": [
{"name": "Computer","type": "string"},
{"name": "TimeGenerated","type": "datetime"},
{"name": "AggregatedValue","type": "real"
}
],
"rows": [
["VPN-Server","2018-02-20T07:30:00Z",5.083333333333333],
["SARMAD-SurfacePro4","2018-02-20T07:30:00Z",14.598250052664012],
["VPN-Server","2018-02-20T07:00:00Z",4.9523809523809526],
["SARMAD-SurfacePro4","2018-02-20T07:00:00Z",12.104500129109331],
["SARMAD-SurfacePro4","2018-02-20T08:00:00Z",20.936097813082174],
["VPN-Server","2018-02-20T08:00:00Z",4.245614035087719]
]
}
]
}
From the sample above, how I can use powershell to convert it to something like this?:
Reportname, Computer, TimeGenerated, AggregatedValue
Manual Value, JsonValue, JsonValue, JsonValue
You can use convertfrom-json and can finally use export-csv to export:
$a='{"tables":[{"name":"PrimaryResult","columns":[{"name":"Computer","type":"string"},{"name":"TimeGenerated","type":"datetime"},{"name":"AggregatedValue","type":"real"}],"rows":[["VPN-Server","2018-02-20T07:30:00Z",5.083333333333333],["SARMAD-SurfacePro4","2018-02-20T07:30:00Z",14.598250052664012],["VPN-Server","2018-02-20T07:00:00Z",4.9523809523809526],["SARMAD-SurfacePro4","2018-02-20T07:00:00Z",12.104500129109331],["SARMAD-SurfacePro4","2018-02-20T08:00:00Z",20.936097813082174],["VPN-Server","2018-02-20T08:00:00Z",4.245614035087719]]}]}'
($a | ConvertFrom-Json).tables.columns.name
Hope it helps.
You can do it similar to this:
function Get-Tables
{
param([Parameter(ValueFromPipeline=$true)]$Json)
process
{
foreach ($table in ($Json | ConvertFrom-Json).tables)
{
foreach ($row in $table.rows)
{
$result = New-Object PSObject
$columnIndex = 0
foreach ($column in $table.columns)
{
Add-Member -InputObject $result -MemberType NoteProperty -Name $column.Name -Value ($row[$columnIndex++])
}
$result
}
}
}
}
$json | Get-Tables | Export-Csv
Where $json is string variable with value from the question example.
$json = '{ "tables": [ ... ] }'

PowerShell How to Add to JSON Array

How do you add to a JSON array in PowerShell? I'm trying with the following code, but it's complaining with a "Collection was of a fixed size" exception:
$json = #"
[
{
"name": "First"
},
{
"name": "Second"
}
]
"#
$toAdd =#"
{
"name": "Third"
}
"#
$jobj = ConvertFrom-Json -InputObject $json
$jobj.Add((ConvertFrom-Json -InputObject $toAdd))
Just use += instead of Add():
$jobj += (ConvertFrom-Json -InputObject $toAdd)
This works.
$js = #"
[
{
"name":"First"
},
{
"name":"Second"
}
]
"#
$toAdd = #"
[
{
"name":"Third"
}
]
"#
$jobj = ConvertFrom-Json -InputObject $js
$jsrc = ConvertFrom-Json -InputObject $toAdd
$jobj = $jobj + $jsrc