Get values from JSON with Powershell

10,007

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!

Share:
10,007
ToastMan
Author by

ToastMan

Nice guy

Updated on June 14, 2022

Comments

  • ToastMan
    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
    ToastMan over 6 years
    Thank you so much for the reply, this was super interesting !
  • ToastMan
    ToastMan over 6 years
    Thank 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
    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
    ToastMan over 6 years
    Hm 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
    ToastMan over 6 years
    if($serviceStatus -eq "False") <-- gives me the exact same results: Enabled Services Name : FAKE Enabled : True Name : TEST00000 Enabled : True
  • BenH
    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
    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
    trebleCode over 6 years
    Yep, 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
    ToastMan over 6 years
    Many 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
    trebleCode over 6 years
    No worries, happy to help anytime