Fetching JSON with PowerShell - How do I fetch all keys under multiple arrays?

284 views Asked by At

I'm trying to build a json file that'll be used in our diverse scripts to fetch our server details. The same script will be used across all our environments that contains multiple products and components. Here's the kind of json file I'm working with:

{
    "DEV" : {
        "Product1" : [
            {"serverName" : "hostname1", "isWebServer" : "true"},
            {"serverName" : "hostname2", "isWebServer" : "false"}
        ],
        "Product2" : [
            {"serverName" : "hostname3", "isWebServer" : "false"},
            {"serverName" : "hostname4", "isWebServer" : "true"}
        ]
    }
}

JSON file is imported into a variable and I'm able to use it successfully.

$jsonFile = Get-Content -Path "C:\temp\test.json" -Raw | ConvertFrom-Json

What I'm trying to do in my PowerShell script is fetch all serverName that is configured with key "isWebServer" : "true"

I can successfully achieve my goal if I'm drilling down on each arrays directly.

($jsonFile.DEV.Product1 | Where-Object {$_.isWebServer -eq "true"}).serverName

However, I'm unable to achieve the same success when I want to fetch all web servers from the whole DEV environment. I'm looking for something like this but that will actually return something.

($jsonFile.DEV | Where-Object {$_.isWebServer -eq "true"}).serverName

How can I fetch everything under all arrays within an object ? I'm used to XPATHs in which I can use wildcards for that kind of scenario but I haven't found the equivalent in JSON.

2

There are 2 answers

0
zett42 On BEST ANSWER

Here is a possible solution:

$json.DEV.PSObject.Properties.Value.Where{ $_.isWebServer -eq 'true' }.serverName

The hidden (intrinsic) PSObject member allows us to access properties (Product1, Product2, ...) of the DEV object, without having to know their names in advance.

Then, using member access enumeration, we get an array of all Value members of the PSPropertyInfo objects stored in PSObject.Properties.

To filter the server objects, the intrinsic method Where is used to return only the servers matching the given condition. Feel free to use Where-Object instead:

$json.DEV.PSObject.Properties.Value | 
    Where-Object isWebServer -eq 'true' | 
    ForEach-Object serverName

Though I prefer the intrinsic methods as they are faster than the pipeline (less overhead) and more succinct to write.

0
Sash Sheen On

It looks similar to what I did a long time ago. See if this helps.