Jq: Creating an array from objects?

Created on 29 Jan 2015  Â·  6Comments  Â·  Source: stedolan/jq

First of all, kudos on such an excellent library...I've used jq for basic CLI tasks and have only recently delved into its more advanced functions, and am continually amazed at how things just work with few surprises...rare for a CLI tool that has so many features...

So I think my question is pretty basic, and I'm missing something very obvious that could be clarified in the docs. Given a series of objects, what do I pipe them through to get them into an array? I've found I can do this:

cat some.json | jq '.[] | { attr1, attr2 }' | jq --slurp '.'

...but, that seems like a workaround...is there a more direct function that I'm missing?

support

Most helpful comment

Thanks for the kudos, we're glad to be useful!

There is! Creating an array from a stream requires knowing when to stop gathering items from the stream, so it isn't done by piping. To create the array (internally we call this collect), just wrap the expression that creates a stream in [ ... ]. So, for your example, cat some.json | jq '[ .[] | { attr1, attr2 }]'. Of course, that's exactly how map/1 is implemented, so you could (and should!) just as easily do cat some.json | jq 'map( { attr1, attr2 })'. Note, you can also put more complex expressions inside of map too.

All 6 comments

Thanks for the kudos, we're glad to be useful!

There is! Creating an array from a stream requires knowing when to stop gathering items from the stream, so it isn't done by piping. To create the array (internally we call this collect), just wrap the expression that creates a stream in [ ... ]. So, for your example, cat some.json | jq '[ .[] | { attr1, attr2 }]'. Of course, that's exactly how map/1 is implemented, so you could (and should!) just as easily do cat some.json | jq 'map( { attr1, attr2 })'. Note, you can also put more complex expressions inside of map too.

....Ah...I knew it would be something simple...but I gave it up after trying this and getting a list of an arrays:

              cat some.json | jq '.[] | [{ attr1, attr2 }]

Which makes sense that that _wouldn't_ work...but I hadn't thought of wrapping the whole expression in brackets...So yes, again, jq was just more sophisticated and natural than I would've expected. Thanks

@wtlangford Thank you for saving me a huge amount of time!

@wtlangford Thank you for pointing out the [ ... ] solution!

I was searching for that… It took me a long time to find it…

Maybe this solution can be put in the manual somewhere? For jq's beginners it's not obvious!

@jolg42 - The section "Array construction - []" in the manual does cover this topic quite comprehensively, and does emphasize the relevant point several times, for example in the paragraph:

If you have a filter X that produces four results, 
then the expression [X] will produce a single result, an array of four elements.

See also the question in the FAQ:

 Q: How can a stream of JSON entities be collected together in an array?

jq-1.5-1-a5b5cbe here

I'm just adding another example because I struggled with merging multiple maps to one.

Maps where not in a list and contained only one entry.

In my case I add to find stuff in aws so I did this:

aws ec2 describe-volumes|jq '.Volumes[]|select(.Encrypted != true)|[{Key: .VolumeId, Value: .Tags?|from_entries|.Name}]|from_entries'
{
  "vol-0e22f37b6b20bdcb7": "active-directory"
}
{
  "vol-032e12cfe27ea6f96": "client1"
}
(...)

Basicly:

{
  "aaa" : "aval"
}
{
  "bbb" : "bval"
}

and the result I wanted was:

{
  "aaa" : "aval",
  "bbb" : "bval"
}

So I added '...|reduce . as $m ({}; . + $m)' which does exactly the same as '...'|jq -s 'add' but is longer

I would have loved a merge function.

But maybe my full jq query has no sense 🤔

anyway hth

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tbelaire picture tbelaire  Â·  4Comments

rclod picture rclod  Â·  4Comments

lhunath picture lhunath  Â·  3Comments

ghost picture ghost  Â·  4Comments

kelchy picture kelchy  Â·  4Comments