Reputation: 265547
I have a JSON array with objects as items. Some of the objects have properties, some don't. How can I filter the list with jq to keep only non-empty objects in the list?
Input:
[
{},
{ "x": 42 },
{},
{ "y": 21 },
{},
{ "z": 13 }
]
Expected output:
[
{ "x": 42 },
{ "y": 21 },
{ "z": 13 }
]
I tried jq 'select(. != {})'
, but the result still contains all items. Using jq 'map(select(empty))'
doesn't keep any item and returns an empty array!
Upvotes: 0
Views: 1379
Reputation: 265547
map
is required to apply the filter to every item in the array. Then any
can be used: it will return true
for objects with at least one property, and false
if the object is empty.
$ jq -n '{} | any'
false
$ jq -n '{x:42} | any'
true
empty
is not a test, but a generator for "no value" (docs).
Solution:
map(select(any))
As noted by user Philippe in the comments, using any
only works if the values of the objects' properties are not false
. It would detect objects such as {"x":false}
as "empty". A better approach is comparing the empty object directly or using length
:
map(select(length>0))
Upvotes: 1
Reputation: 2210
Just use the del
filter:
jq 'del(.[] | select(length == 0))'
or
jq 'del(.[] | select(. == {}))'
Upvotes: 0
Reputation: 26697
You need map
to make select
test individual objects:
jq 'map(select(. != {}))'
Upvotes: 1