Get values from JSON with Powershell
Solution 1
To get the name of each Services
property. You can use Get-Member
like user2734259 did or you can use the psobject
property which stores useful information about an object.
$ServiceNames = $jsonobj.Envs.DEV.Services.psobject.properties.name
Once you have the names you can loop over them and filter on the sub-property Enabled
$jsonobj.Envs.DEV.Services.psobject.properties.name | ForEach-Object {
$_ | Where-Object {$jsonobj.Envs.DEV.Services.$_.Enabled -eq $True}
}
Solution 2
This should allow you to get the names dynamically, regardless of the service name in your JSON:
$JSON = '{
"Envs": {
"DEV": {
"Services": {
"TEST00000": {
"Enabled": true,
"Processed": 2,
"Sent": 3,
"Failed": 4,
"Downloaded": 5
},
"FAKE": {
"Enabled": true
}
}
}
},
"Component": {
"Digger": {
"Envs": {
"DEV": {
"DownloadE": 4
}
}
}
}
}'
$jsonobj = ConvertFrom-Json -inputObject $JSON
$enabledServices = $NULL
$disabledServices = $NULL
# Since the service names are arbitrary
# create an object that contains only
# objects whose MemberType is NoteProperty
$strServiceNames = @($($jsonobj.Envs.DEV.Services | Get-Member | Where { $_.MemberType -eq "NoteProperty" } | Select Name).Name)
$pscoServiceNames = [PSCustomObject]@{Names=$strServiceNames}
foreach($serviceName in $pscoserviceNames.Names)
{
# dynamically access the service name
# from $jsonobj.Envs.DEV.Services
$serviceStatus = $jsonobj.Envs.DEV.Services.$serviceName.Enabled
# parse results based on value of .Enabled
if($serviceStatus.ToString() -eq "True")
{
$enabledServices = [Array]$enabledServices + [PSCustomObject]@{Name = $serviceName;Enabled = $serviceStatus}
}
else
{
$disabledServices = [Array]$disabledServices + [PSCustomObject]@{Name = $serviceName;Enabled = $serviceStatus}
}
}
# Show the results
Write-Output "`nEnabled Services`n"
$enabledServices | Format-List
Write-Output "`nDisabled Services`n"
$disabledServices | Format-List
If anything is unclear let me know and I can explain in more detail Hope this helps you out. Happy 'shelling!
Comments
-
ToastMan almost 2 years
Very beginner question. I'm trying to get certain values from JSON with Powershell.. Specifically, I want to list the Services: TEST00000 and FAKE only.
When I run the script below, I get this:
TEST00000 FAKE --------- ---- @{Enabled=True; Processed=2; Sent=3; Failed=4; Downloaded=5} @{Enabled=True}
How can I get a list of only the services?
More importantly, how do I list only the services which has the key/value Enabled=True present inside of them?
Here is the code:
$JSON = '{ "Envs": { "DEV": { "Services": { "TEST00000": { "Enabled": true, "Processed": 2, "Sent": 3, "Failed": 4, "Downloaded": 5 }, "FAKE": { "Enabled": true } } } }, "Component": { "Digger": { "Envs": { "DEV": { "DownloadE": 4 } } } } }' $jsonobj = ConvertFrom-Json -inputObject $JSON $jsonobj.Envs.DEV.Services
-
ToastMan over 6 yearsThank you so much for the reply, this was super interesting !
-
ToastMan over 6 yearsThank you so much for the reply, this was super interesting, I spent a lot of time trying to look for this info, how did you guys learn this? Where can I do further reading about this? (or is it learning the art of using the PS help content!?)
-
BenH over 6 years@ToastMan I personally started with the Don Jones Month of Lunches books. Knowing about the hidden
psobject
property I picked up on from someone's answer on SO (been too long to remember who). -
ToastMan over 6 yearsHm the last part doesn't seem to work: $_ | Where-Object {$jsonobj.Envs.DEV.Services.$_.Enabled -eq 'false'} <-- lists the services anyways (with the -eq 'false')
-
ToastMan over 6 yearsif($serviceStatus -eq "False") <-- gives me the exact same results: Enabled Services Name : FAKE Enabled : True Name : TEST00000 Enabled : True
-
BenH over 6 years@ToastMan Updated my answer to fix the issue. This was because the
Enabled
property is a boolean. And when you try to cast the string'false'
to a boolean, it turns into$True
. You can test this with[bool]'false'
. -
trebleCode over 6 years@toastman I will revisit when I'm back at the machine where I wrote the code and fix if necessary and edit my answer for the sake of completeness. Think it might be a type problem but will check. Til then, happy holidays
-
trebleCode over 6 yearsYep, it was a type error. $serviceStatus is boolean so it needed to be converted to a string to match the regex. So just change that one line to:
if($serviceStatus.ToString() -eq "False")
and it should work as needed -
ToastMan over 6 yearsMany thanks trebleCode. I ended up marking BenH response as the solution as I used his code at the end. But I highly appreciate your help.
-
trebleCode over 6 yearsNo worries, happy to help anytime