pje
pje

Reputation: 22747

In jq, what's the difference between `.my_array` and `.my_array[]`?

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

Answers (3)

Weeble
Weeble

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

chepner
chepner

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

peak
peak

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

Related Questions