Reputation: 22747
I'm new to JQ and I'm having trouble wrapping my head around the return types of JQ's filters when applied to arrays.
Specifically: What's the difference between .my_array
and my_array[]
?
The first example returns an array:
$ echo '{"my_array":[{"id":1},{"id":2}]}' | jq '.my_array'
[
{
"id": 1
},
{
"id": 2
}
]
While the second example seems to return each element of the array:
$ echo '{"my_array":[{"id":1},{"id":2}]}' | jq '.my_array[]'
{
"id": 1
}
{
"id": 2
}
What's the precise difference between "filter that returns an array" and "filter that returns each element of the array", and why does JQ consider them different?
Upvotes: 0
Views: 912
Reputation: 17960
The point to understand is that all filters emit a stream of zero or more JSON entities. When your first example reads in one JSON object, it places one JSON array onto its output stream:
echo '{"my_array":[{"id":1},{"id":2}]}' | jq '.my_array'
[
{
"id": 1
},
{
"id": 2
}
]
When your second example reads in one JSON object it emits two JSON objects onto its output stream:
$ echo '{"my_array":[{"id":1},{"id":2}]}' | jq '.my_array[]'
{
"id": 1
}
{
"id": 2
}
A lot of jq
will make more sense once you understand that filters can be composed together and all filters output streams. The filter .my_array[]
can be seen as two filters composed together, .myarray
and .[]
. We've already seen what .myarray
does on its own: every time it reads in an object, it places one entity on its output stream, either the value of that field or null
if it was missing. When the two filters are composed together, each output from the first is fed into the second. Every time .[]
reads in an array, it places all of that array's contents, one at a time, on its output stream.
Upvotes: 1
Reputation: 532133
Consider a filter that would do something with the result of each of your two filters. This might make it clearer than simply seeing the value(s) written to standard output.
First, we create an object from the single array value produced by .my_array
. The entire array becomes the value of the key x
.
% echo '{"my_array":[{"id":1},{"id":2}]}' | jq '{x: .my_array}'
{
"x": [
{
"id": 1
},
{
"id": 2
}
]
}
Next, we create two objects, one for each object value produced by .my_array[]
.
% echo '{"my_array":[{"id":1},{"id":2}]}' | jq '{x: .my_array[]}'
{
"x": {
"id": 1
}
}
{
"x": {
"id": 2
}
}
Upvotes: 1
Reputation: 116957
Perhaps the key concept you have not grasped is that of a "stream". jq can be thought of as a stream-oriented language so you might find the following helpful:
https://github.com/pkoppstein/jq/wiki/A-Stream-oriented-Introduction-to-jq
Disclosure: I am the author.
Upvotes: 2