My JSON looks like:
{
"foo": {
"restricted": true
},
"bar": {
"restricted": false
},
"baz": { }
}
As single line:
{"foo":{"restricted":true},"bar":{"restricted":false},"baz":{}}
I want to get all top-level attribute keys returned which are either restricted == false
or don't have the restricted
subattribute. With above example JSON, the expected output is:
"bar"
"baz"
答案 0 :(得分:2)
I came up with the following expression:
jq "to_entries[] | select(.value.restricted|not) | .key"
to_entries
converts the top-level object to an array of objects with a "key"
and a "value"
attribute each:
[
{
"key": "foo135",
"value": {
"restricted": true
}
},
{
"key": "foo246",
"value": {
"restricted": false
}
},
{
"key": "foo345",
"value": {}
}
]
[]
explodes this array. This is done in order to filter individual objects in the next step:
{
"key": "foo135",
"value": {
"restricted": true
}
}
{
"key": "foo246",
"value": {
"restricted": false
}
}
{
"key": "foo345",
"value": {}
}
Then a filter is applied for each object: select(.value.restricted|not)
. To filter out attributes with the subattribute restricted
being truthy, .value.restricted
can be inverted with |not
to select objects with restricted == false
as well as objects without this attribute using a single condition:
{
"key": "foo246",
"value": {
"restricted": false
}
}
{
"key": "foo345",
"value": {}
}
Finally, the "key"
attribute is selected: .key
. This returns the names of the matching objects (originally the top-level attribute keys):
"foo246"
"foo345"
Note that the pipe character |
in select(...) | .key
isn't strictly needed. The result is the same without.
If a string array is desired as result...
[
"foo246",
"foo345"
]
... then the following expression can be used:
jq "to_entries | map(select(.value.restricted|not).key)"
As you can see, select()
can be used inside of map()
to filter out individual elements, and it can even be combined with the attribute filter .key
.
If you append []
at the end like map(...)[]
, then the array gets exploded and the result is a list of strings again, like in the initial example, but using a slightly different approach.