The |= .+ part in the filter adds a new element to the existing array. You can use jq with filter like:

jq '.data.messages[3] |= . + {
      "date": "2010-01-07T19:55:99.999Z", 
      "xml": "xml_samplesheet_2017_01_07_run_09.xml", 
      "status": "OKKK", 
      "message": "metadata loaded into iRODS successfullyyyyy"
}' inputJson

To avoid using the hardcoded length value 3 and dynamically add a new element, use . | length which returns the length, which can be used as the next array index, i.e.,

jq '.data.messages[.data.messages| length] |= . + {
      "date": "2010-01-07T19:55:99.999Z", 
      "xml": "xml_samplesheet_2017_01_07_run_09.xml", 
      "status": "OKKK", 
      "message": "metadata loaded into iRODS successfullyyyyy"
}' inputJson

(or) as per peak's suggestion in the comments, using the += operator alone

jq '.data.messages += [{
     "date": "2010-01-07T19:55:99.999Z",
     "xml": "xml_samplesheet_2017_01_07_run_09.xml", 
     "status": "OKKK", 
     "message": "metadata loaded into iRODS successfullyyyyy"
}]'

which produces the output you need:

{
  "report": "1.0",
  "data": {
    "date": "2010-01-07",
    "messages": [
      {
        "date": "2010-01-07T19:58:42.949Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "OK",
        "message": "metadata loaded into iRODS successfully"
      },
      {
        "date": "2010-01-07T20:22:46.949Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "NOK",
        "message": "metadata duplicated into iRODS"
      },
      {
        "date": "2010-01-07T22:11:55.949Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "NOK",
        "message": "metadata was not validated by XSD schema"
      },
      {
        "date": "2010-01-07T19:55:99.999Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "OKKK",
        "message": "metadata loaded into iRODS successfullyyyyy"
      }
    ]
  }
}

Use jq-play to dry-run your jq-filter and optimize any way you want.

Answer from Inian on Stack Overflow
Top answer
1 of 4
192

The |= .+ part in the filter adds a new element to the existing array. You can use jq with filter like:

jq '.data.messages[3] |= . + {
      "date": "2010-01-07T19:55:99.999Z", 
      "xml": "xml_samplesheet_2017_01_07_run_09.xml", 
      "status": "OKKK", 
      "message": "metadata loaded into iRODS successfullyyyyy"
}' inputJson

To avoid using the hardcoded length value 3 and dynamically add a new element, use . | length which returns the length, which can be used as the next array index, i.e.,

jq '.data.messages[.data.messages| length] |= . + {
      "date": "2010-01-07T19:55:99.999Z", 
      "xml": "xml_samplesheet_2017_01_07_run_09.xml", 
      "status": "OKKK", 
      "message": "metadata loaded into iRODS successfullyyyyy"
}' inputJson

(or) as per peak's suggestion in the comments, using the += operator alone

jq '.data.messages += [{
     "date": "2010-01-07T19:55:99.999Z",
     "xml": "xml_samplesheet_2017_01_07_run_09.xml", 
     "status": "OKKK", 
     "message": "metadata loaded into iRODS successfullyyyyy"
}]'

which produces the output you need:

{
  "report": "1.0",
  "data": {
    "date": "2010-01-07",
    "messages": [
      {
        "date": "2010-01-07T19:58:42.949Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "OK",
        "message": "metadata loaded into iRODS successfully"
      },
      {
        "date": "2010-01-07T20:22:46.949Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "NOK",
        "message": "metadata duplicated into iRODS"
      },
      {
        "date": "2010-01-07T22:11:55.949Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "NOK",
        "message": "metadata was not validated by XSD schema"
      },
      {
        "date": "2010-01-07T19:55:99.999Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "OKKK",
        "message": "metadata loaded into iRODS successfullyyyyy"
      }
    ]
  }
}

Use jq-play to dry-run your jq-filter and optimize any way you want.

2 of 4
79

Rather than using |=, consider using +=:

.data.messages += [{"date": "2010-01-07T19:55:99.999Z",
   "xml": "xml_samplesheet_2017_01_07_run_09.xml",
   "status": "OKKK", "message": "metadata loaded into iRODS successfullyyyyy"}]

Prepend

On the other hand, if (as @NicHuang asked) you want to add the JSON object to the beginning of the array, you could use the pattern:

 .data.messages |= [ _ ] + .
Top answer
1 of 4
24

jq has a flag for feeding actual JSON contents with its --argjson flag. What you need to do is, store the content of the first JSON file in a variable in jq's context and update it in the second JSON

jq --argjson groupInfo "$(<input.json)" '.[].groups += [$groupInfo]' orig.json

The part "$(<input.json)" is shell re-direction construct to output the contents of the file given and with the argument to --argjson it is stored in the variable groupInfo. Now you add it to the groups array in the actual filter part.

Putting it in another way, the above solution is equivalent of doing this

jq --argjson groupInfo '{"id": 9,"version": 0,"lastUpdTs": 1532371267968,"name": "Training" }' \
   '.[].groups += [$groupInfo]' orig.json
2 of 4
15

This is the exact case that the input function is for:

input and inputs [...] read from the same sources (e.g., stdin, files named on the command-line) as jq itself. These two builtins, and jq’s own reading actions, can be interleaved with each other.

That is, jq reads an object/value in from the file and executes the pipeline on it, and anywhere input appears the next input is read in and is used as the result of the function.

That means you can do:

jq '.[].groups += [input]' orig.json input.json

with exactly the command you've written already, plus input as the value. The input expression will evaluate to the (first) object read from the next file in the argument list, in this case the entire contents of input.json.

If you have multiple items to insert you can use inputs instead with the same meaning. It will apply across a single or multiple files from the command line equally, and [inputs] represents all the file bodies as an array.

It's also possible to interleave things to process multiple orig files, each with one companion file inserted, but separating the outputs would be a hassle.

Discussions

jq append data and keep the rest - Unix & Linux Stack Exchange
The && prevents the original file from being overwritten if jq for some reason fails. ... Find the answer to your question by asking. Ask question ... See similar questions with these tags. ... 0 How to parse markdown text from JSON and appending it to a file without ruining the markdown formatting? More on unix.stackexchange.com
🌐 unix.stackexchange.com
Using jq to add/prepend an element to the top of an array - Stack Overflow
I'd like to use jq to add a new element to the top of this array (rather than the bottom). More on stackoverflow.com
🌐 stackoverflow.com
Adding unique item to array
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. ... I think this question indicates that I don't quite get how jq works. More on github.com
🌐 github.com
5
November 30, 2013
bash - How do I use jq to append an array to this json string? - Stack Overflow
I want to append this array to this json string using jq. My result only adds the hello element method=1234 arraynew=(hello world) echo $arraynew PAYLOAD=$( jq -Rn \ --arg method $ More on stackoverflow.com
🌐 stackoverflow.com
🌐
Baeldung
baeldung.com › home › files › file editing › how to add objects into json array using jq
How to Add Objects Into JSON Array Using jq | Baeldung on Linux
March 18, 2024 - ‘.posts += [$p]’ is the jq filter to update the posts array: .posts selects the posts field · += appends to the array · [$p] puts the contents of p into the array · blog.json is the JSON file on which we’re operating ·
🌐
GitHub
gist.github.com › joar › 776b7d176196592ed5d8
Add a field to an object with JQ · GitHub
echo '{"hello": {"value": "world"}}' | jq '.hello.other_key = "new_val"' Copy link · Copy Markdown · Example for adding an element to an array: $ echo '[ {"data1":"A"}, {"data2":"B"} ]' | jq --arg val True '.[] += {uppercase: $val}' [ { "data1": "A", "uppercase": "True" }, { "data2": "B", "uppercase": "True" } ] Copy link ·
🌐
Petermekhaeil
petermekhaeil.com › til › jq-append-json
Add an object to existing JSON using jq
# Optional: Create new JSON file `feed.json` with empy array. jq -n '[]' > feed.json # Append an object to the array from `feed.json` # and store the new JSON in `feed.json.tmp` jq \ --arg date "$date" \ --arg title "$title" \ '. += [{"date": ...
🌐
iO Flood
ioflood.com › blog › jq-array
Manipulating JSON Arrays with jq | Example Guide
November 15, 2023 - The commands follow common syntax such as, creating arrays and adding elements with echo '[]' | jq '. +=', indexing with .["indexNumber"], modifying elements with .["indexNumber"] = "New Value" .
🌐
how.wtf
how.wtf › add-new-element-to-json-array-with-jq.html
Add new element to JSON array with jq | how.wtf
March 19, 2023 - Adding a new element to an existing JSON array can be completed using jq. This is a generic projects.json file: 1{ 2 "projects": [ 3 { 4 "id": 1, 5 "version": "2.3.0" 6 }, 7 { 8 "id": 2, 9 "version": "1.54.0" 10 } 11 ] 12} Appending a new element to the array can be completed in two ways: 1.
Find elsewhere
🌐
GitHub
github.com › jqlang › jq › issues › 226
Adding unique item to array · Issue #226 · jqlang/jq
November 30, 2013 - $ echo "$DATA" | jq ".ignore += [\"b\"]" { "generic": [ "a" ], "ignore": [ "b", "b" ], "playServer": [ "c" ], "postgresServer": [ "d" ] } This gives me a duplicate item. I can use unique to eliminate the duplicate:
Author   mslinn
🌐
IQCode
iqcode.com › code › javascript › jq-append-value-to-array
jq append value to array Code Example
August 27, 2021 - jq '.data.messages += [{&quot;date&quot;: &quot;2010-01-07T19:55:99.999Z&quot;, &quot;xml&quot;: &quot;xml_samplesheet_2017_01_07_run_09.xml...
🌐
Stack Overflow
stackoverflow.com › questions › 69760036 › how-do-i-use-jq-to-append-an-array-to-this-json-string
bash - How do I use jq to append an array to this json string? - Stack Overflow
#!/usr/bin/env bash method=1234 arraynew=(hello world) declare -p arraynew payload=$( printf '%s\0' "${arraynew[@]}" | jq -Rs '{method: $method, values: split("\u0000")}' \ --arg method "$method" ) printf '%s\n' "$payload" ... Find the answer to your question by asking.
🌐
Exercism
exercism.org › tracks › jq › concepts › arrays
Arrays in jq on Exercism
Master Arrays in jq by solving 5 exercises, with support from our world-class team.
🌐
Stack Overflow
stackoverflow.com › questions › 71869690 › how-to-append-a-object-to-a-array
jq - How to append a object to a array? - Stack Overflow
April 14, 2022 - I have a input json file as this, { "foo":[ "key1", "key2" ], "bar": "key3" } Here is how the jq filter defined, [.[] | . as { f...