In jq 1.3 and up you can use the --arg VARIABLE VALUE command-line option:

jq -n --arg v "$VAR" '{"foo": $v}'

I.e., --arg sets a variable to the given value so you can then use $varname in your jq program, and now you don't have to use shell variable interpolation into your jq program.

EDIT: From jq 1.5 and up, you can use --argjson to pass in an array directly, e.g.

jq -n --argjson v '[1,2,3]' '{"foo": $v}'
Answer from user2259432 on Stack Overflow
Discussions

bash - Add JSON objects to array using jq - Unix & Linux Stack Exchange
I tried adding the square brackets to the jq output string for each line ('[{name: $name, path: $path}]';) and that adds the brackets but not the commas between the array elements. More on unix.stackexchange.com
🌐 unix.stackexchange.com
February 26, 2020
bash - jq - create empty array and add objects to it - Stack Overflow
I am working on a bash script (using jq for JSON parsing) that needs to make multiple CURL calls (response has same structure but different values), apply some logic/filters and then collate all the More on stackoverflow.com
🌐 stackoverflow.com
jq - add objects from file into json array - Unix & Linux Stack Exchange
It will apply across a single or ... 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. ... But this probably doesn't let me incorporate non-json files. With --arg I can do: jq --arg "$(<1.txt)" ... More on unix.stackexchange.com
🌐 unix.stackexchange.com
bash - jq: output array of json objects - Stack Overflow
44 How to convert a JSON object stream into an array with jq More on stackoverflow.com
🌐 stackoverflow.com
🌐
GitHub
github.com › jqlang › jq › issues › 684
Creating an array from objects? · Issue #684 · jqlang/jq
January 29, 2015 - 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?
Author   dannguyen
🌐
Exercism
exercism.org › tracks › jq › concepts › arrays
Arrays in jq on Exercism
[range(10)] - [2, 4, 6] # => [0, 1, 3, 5, 7, 8, 9] jq provides many functions to cover common iteration functionality: map(expr) returns a new array where the expr is applied to each element in turn.
🌐
Programming Historian
programminghistorian.org › en › lessons › json-and-jq
Reshaping JSON with jq | Programming Historian
May 24, 2016 - Both of these commands are wrapped in [] which tells jq to collect every result into one single array, which is passed with a | along to: join(";"), which turns that array into one single character string, with semicolon delimiters between multiple tweet ids. This filter created new JSON.
🌐
jq
jqlang.org › manual
jq 1.8 Manual
A jq program is a "filter": it takes an input, and produces an output. There are a lot of builtin filters for extracting a particular field of an object, or converting a number to a string, or various other standard tasks. Filters can be combined in various ways - you can pipe the output of one filter into another filter, or collect the output of a filter into an array...
Find elsewhere
🌐
iO Flood
ioflood.com › blog › jq-array
Manipulating JSON Arrays with jq | Example Guide
November 15, 2023 - Here’s a simple example of creating an array: echo '[]' | jq '. += ["element"]' # Output: # ["element"]
🌐
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 - $ jq '.posts += [inputs]' blog.json post-1.json post-2.json · Once executed, it produces a JSON with all the posts inside the array:
🌐
Qmacro
qmacro.org › blog › posts › 2022 › 05 › 06 › converting-strings-to-objects-with-jq
Converting strings to objects with jq - DJ Adams
May 6, 2022 - In preparing some data for another upcoming blog post (now published: Exploring GitHub repo name distribution with jq), I needed to convert a list of fully qualified GitHub repository names into a JSON array of single-property objects (to reflect the style of JSON output from GitHub's gh CLI).
🌐
jq recipes
remysharp.com › drafts › jq-recipes
jq recipes
April 16, 2024 - echo "1\n2\n3" | jq --slurp --raw-input 'split("\n")[:-1]' ... Convert a plain list of timestamps to an array of objects with date and time separated (using jq's --slurp and --raw-input options combined):
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.

🌐
Cameronnokes
cameronnokes.com › blog › jq-cheatsheet
JQ cheatsheet - Cameron Nokes
August 5, 2020 - Joins the elements of an array using a separator. echo '{ "firstName": "Cameron", "lastName": "Nokes" }' | jq '[.firstName, .lastName] | join(" ")' # Cameron Nokes · We create an array of the properties we want joined, pipe to join which is passed a space as the separator.
🌐
Earthly
earthly.dev › blog › jq-select
JQ Select Explained: Selecting elements from JSON with Examples - Earthly Blog
July 24, 2023 - This syntax is the same syntax for creating an object in a JSON document. The only difference is you can use the object and array queries you’ve built up as the values. Returning to my GitHub API problem, to wrap the number and the title up into an array I use the object constructor like this: $ curl https://api.github.com/repos/stedolan/jq/issues?per_page=2 | \ jq '[ .[] | { title: .title, number: .number} ]'
Top answer
1 of 2
4

Pass your strings using --arg, then you can create the JSON as expected:

#!/bin/bash

server1_name='server-1'
server1_url='http://server-1.net'

server2_name='server-2'
server2_url='http://server-2.net'

result=$(jq -n \
    --arg name1 "$server1_name" \
    --arg url1 "$server1_url" \
    --arg name2 "$server2_name" \
    --arg url2 "$server2_url" \
    '[ { "name": $name1, "url": $url1 }, { "name": $name2, "url": $url2 } ]')

echo "$result"

Will produce:

[
  {
    "name": "server-1",
    "url": "http://server-1.net"
  },
  {
    "name": "server-2",
    "url": "http://server-2.net"
  }
]
2 of 2
1

You can construct two arrays of names and urls, then adapt this answer to "zip" the two arrays together into the desired array of objects.

jq -n \
    --arg name1 "$server1_name" \
    --arg url1 "$server1_url" \
    --arg name2 "$server2_name" \
    --arg url2 "$server2_url" \
'[$name1, $name2] as $names |
 [$url1, $url2] as $urls |
  [([$names, $urls] | transpose[]) as [$name, $url] |{$name, $url}]'

The benefit is that as the number of name/url pairs grows, you only need to modify the first two filters that define $names and $urls; the rest of the filter stays the same. You could even separate this into separate uses of jq, to facilitate the definition of a large list of servers.

names=$(jq -n --arg v1 "$server1_name" --arg v2 "$server2_name" '[$v1, $v2]')

urls=$(jq -n --arg v1 "$server1_url" --arg v2 "$server2_url" '[$v1, $v2]')

jq -n \
   --argjson names "$names" \
   --argjson urls "$urls" \
   '[([$names, $urls] | transpose[]) as [$name, $url] | {$name, $url}]'