knittl
knittl

Reputation: 265547

Select only non-empty objects from array

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

Answers (3)

knittl
knittl

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

jpseng
jpseng

Reputation: 2210

Just use the del filter:

jq 'del(.[] | select(length == 0))'

or

jq 'del(.[] | select(. == {}))'

Upvotes: 0

Philippe
Philippe

Reputation: 26697

You need map to make select test individual objects:

jq 'map(select(. != {}))'

Upvotes: 1

Related Questions