2

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

2 Answers 2

4

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

A similar approach is using the intrinsic method .Where{}:

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

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

Intrinsic methods like .Where{} 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 with parameter -ExpandProperty (alias -Expand), 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 } 
Sign up to request clarification or add additional context in comments.

Comments

3

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.