Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jq select attribute if any array element satisfies a condition

Tags:

json

select

jq

any

With the help of jq i would like to select all addresses of nodes that have at least one required=true in their attribute list. The result list should have unique items.

Here is my Json:

{
"nodes": [
    {
        "address":"127.0.0.1",
        "attributes": [
            {
                "id":"abc",
                "required":true
            },
            {
                "id":"def",
                "required":true
            },
            {
                "id":"ghi",
                "required":false
            }
        ]
    },
    {
        "address":"127.0.0.2",
        "attributes": [
            {
                "id":"abc",
                "required":false
            },
            {
                "id":"def",
                "required":false
            }
        ]
    }
]
}

I first tried with:

jq '.nodes[] | select(.attributes[].required == true) | .address'

This produces:

"127.0.0.1"
"127.0.0.1"

So it gets the address for every required=true field it finds in the attributes section. How to make the result list unique? There is also a unique keyword in jq, but I couldn't figure out how this could help me.

like image 423
Peter Lutz Avatar asked Oct 07 '16 10:10

Peter Lutz


1 Answers

Using unique is safe but it does require sorting, which may not be necessary. In your particular case, for example, the repetition is an artifact of the jq query. Consider using any instead (or as well), as it more precisely captures the intention ("at least one"), as well as having "short-circuit" semantics (i.e., it stops searching once the condition is true):

$ jq '.nodes[]
| select( any(.attributes[]; .required == true))
| .address' input.json

Output:

"127.0.0.1"

You can always add unique if necessary.

like image 136
peak Avatar answered Oct 22 '22 11:10

peak