Home > OS >  Get specific value from JSON array after comparison using PowerShell?
Get specific value from JSON array after comparison using PowerShell?

Time:02-11

I want to get specific value once key is matched from JSON array object

Input:

[
    {
        "Id": "19A7A3C4",
        "displayName": "somename",
        "tags": [
            {
                "context": "CONTEXTLESS",
                "key": "apple",
                "value": "10"
            },
            {
                "context": "CONTEXTLESS",
                "key": "orange",
                "value": "20"
            },
            {
                "context": "CONTEXTLESS",
                "key": "grapes",
                "value": "30"
            }
        ]
    },
    {
        "Id": "111111",
        "displayName": "somename",
        "tags": [
            {
                "context": "CONTEXTLESS",
                "key": "cat",
                "value": "10"
            },
            {
                "context": "CONTEXTLESS",
                "key": "cat",
                "value": "20"
            }
        ]
    }
]

I want to get the value of tag where key matches to cat and value matches to 10, I am using below query but getting whole object

$content = Get-Content -Raw -Path "data.json" | ConvertFrom-Json
$content | Where-Object{ $_.tags.key -eq "cat" -and $_.tags.value -eq "10"}

Desired Output: 10

CodePudding user response:

Enumerate all tags, then use ForEach-Object to grab just the value property of any match:

$content.tags | Where-Object { $_.key -eq "cat" -and $_.value -eq "10"} |ForEach-Object -MemberName value

CodePudding user response:

Mathias's answer already shows a clean way to solve the problem.

A similar approach is using using an array method:

$tagValues = $content.tags.Where{ $_.key -eq "cat" -and $_.value -eq "10" }.value

$content.tags employs member enumeration to collect all tag properties into an array. .Where{} is an array method that filters array elements similar to Where-Object. Lastly .value uses member enumeration again to collect all tag values into an array.

Array methods are supposed to be faster than pipeline commands because they don't involve the overhead of the pipeline machinery.


If you want to keep your original query, you have to deal with nested properties.

Use grouping operator () and dot notation to extract a given property:

$tagValues = ($content | Where-Object{ $_.tags.key -eq "cat" -and $_.tags.value -eq "10"}).tags.value

An alternative is Select-Object, but it doesn't work as straightforward for nested properties (yet):

$tagValues = $content | Where-Object{ $_.tags.key -eq "cat" -and $_.tags.value -eq "10"} |
    Select-Object -Expand tags | Select-Object -Expand value

A more straightforward alternative is ForEach-Object:

$tagValues = $content | Where-Object{ $_.tags.key -eq "cat" -and $_.tags.value -eq "10"} |
    ForEach-Object { $_.tags.value } 
  • Related