Merge Arbitrary Amount of Arrays into Single Array?

Viewed 72

I have a series of JSON files that I've been working with via jq. Each file consists of an array of dictionaries, e.g.

  • file1.json: [{ "id": 1 }]
  • file2.json: [{ "id": 2 }]

The only command I have found which successfully merges all input files into one output array is:

jq --slurp '.[0] + .[1]' file1.json file2.json

This command outputs [{ "id": 1 }, { "id": 2 }], as expected.

I'm writing a shell script which is expected to merge a variable set of files into a single JSON array as an output. My script will execute something like:

find . -type f -iname '*.json' | xargs jq 'FILTER'

This should invoke jq like jq 'FILTER' file1.json file2.json ....

Is there a feature that I'm missing that will take all input files and first merge them into one contiguous list of objects without having to rewrite the filter to something like .[0] + .[1] + .[2] ...?

2 Answers

Given:

1.json

[{ "id": 1 }]

2.json

[{ "id": 2 }]

3.json

[{ "id": 3 }]

Then this command:

jq --slurp 'map(.[])' 1.json 2.json 3.json

Returns:

[
  {
    "id": 1
  },
  {
    "id": 2
  },
  {
    "id": 3
  }
]

Or simply:

jq --slurp 'flatten' 1.json 2.json 3.json

It's generally best to avoid the -s option, especially if your version of jq supports inputs, as do all versions >= 1.5.

In any case, if your version of jq supports inputs, you could write:

jq -n '[inputs[]]' 1.json 2.json 3.json # etc

or whichever variant meets your needs.

Otherwise, you could simply write:

jq -s add 1.json 2.json 3.json # etc

Note on flatten

flatten itself is ruthless:

$ jq flatten <<< '[[[1], [[[[2]]]]]]'
[1,2]

flatten(1) is less so.

Related