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

Creating Array of Objects from Bash Array using jq - Stack Overflow
I am trying to create an array of objects in bash given an array in bash using jq. Here is where I am stuck: IDS=("baf3eca8-c4bd-4590-bf1f-9b1515d521ba" "ef2fa922-2038-445c-9d32- More on stackoverflow.com
🌐 stackoverflow.com
More fun with jq, getting results into a usable array
It's better practice to not chain together results within $() or backticks. Unless you're expecting a huge volume of data returned from your curl calls, it's better to capture it's result directly, so you can explicitly check for failure of the curl call itself, and failure of the request. If it looks valid, then proceed to parse it as you wish. It looks like you might not need to put your fields into arrays. You might be able to use jq -c to iterate through your initial curl call result, and then pull the values you need into separate variables, which you can then use to make the next requests. Something like: foo=$( curl something ) || { echo >&2 "curl failed"; exit 1; } # check $foo for http errors if $foo invalid; then exit 1; fi json_from_foo=$( filter_result "$foo" ) || { echo >&2 "failed to extract json from result"; exit 1; } for json_record in $( jq -c '.[]' <<< "$json_from_foo); do action=$(jq -r '.action' <<< $json_record) expr=$(jq -r '.expression' <<< $json_record) desc=$(jq -r '.description' <<< $json_record) process_record "$action" "$expr" "$desc" done More on reddit.com
🌐 r/bash
2
2
August 17, 2024
Assigning an Array Parsed With jq to Bash Script Array - Stack Overflow
The following bash script populates an array, x, with JSON texts. The key points are the use of the -c option, and the use of the bash idiom while read -r value; do ... done < <(jq .......): #!/bin/bash x=() while read -r value do x+=("$value") done < <(jq -c '.[]' input.json) ... ++ Since I am not aware of you input file, I am creating ... More on stackoverflow.com
🌐 stackoverflow.com
ubuntu - parse one field from an JSON array into bash array - Unix & Linux Stack Exchange
Note that bash's readarray now supports readarray -td '' to read NUL-delimited data into an array. ... which is then evaluated by your shell. Evaluating that string will create the named array arr with the two elements value2 and value2_2: $ eval "$( jq -r '@sh "arr=( \([.[].item2]) )"' file.json ... More on unix.stackexchange.com
🌐 unix.stackexchange.com
🌐
Cameronnokes
cameronnokes.com › blog › working-with-json-in-bash-using-jq
Working with JSON in bash using jq - Cameron Nokes
August 1, 2020 - Also, be sure to always wrap your jq selector in a single-quotes, otherwise bash tries to interpret all the symbols like ., whereas we want jq to do that. Now let’s see how iteration works. The array or object value iterator operator, .[] , is what makes it possible.
🌐
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.
🌐
Reddit
reddit.com › r/bash › more fun with jq, getting results into a usable array
r/bash on Reddit: More fun with jq, getting results into a usable array
August 17, 2024 -

I'm using this in a cURL to get the data from result[]:

foo=$(curl --request GET \
--silent \
--url https://example.com \
--header 'Content-Type: application/json' | jq -r '.result[]')

When I print $foo, this is what I have:

[key]
default

firewall_custom
zone
34
[
  {
    "id": "example",
    "version": "6",
    "action": "block",
    "expression": "lorem",
    "description": "ipsum",
    "last_updated": "2024-08-15T19:10:24.913784Z",
    "ref": "example",
    "enabled": true
  },
  {
    "id": "example2",
    "version": "7",
    "action": "block",
    "expression": "this",
    "description": "that",
    "last_updated": "2024-08-15T19:10:24.913784Z",
    "ref": "example2",
    "enabled": true
  }
]

What I need from this is to create a loop where, in a series of addtional cURLs, I can insert action, expression, and description.

I'm imagining that I would push these to 3 separate arrays (action, expression, and description), so that ${action[0]} would coincide with ${expression[0]} and ${description[0]}, and so on.

Something along the lines of:

# assuming that I have somehow created the following arrays:
# action=("block" "block")
# expression=("lorem" "this")
# description=("ipsum" "that")

for x in ${action[@]}; do
  bar=$(curl --request GET \
    --silent \
    --url https://example.com \
    --data '{
      "action": ${action[$x]},
      "expression": ${expression[$x]},
      "description": ${description[$x]}
    }' | jq '.success')

  if [[ $bar == true ]]
    then
      printf "$x succeeded\n"

    else
      printf "$x failed\n"
  fi

  # reset bar
  bar=''
done

The question is, how to create action, expression, and description arrays from the results of $foo (that original cURL)?

🌐
Baeldung
baeldung.com › home › web › guide to linux jq command for json processing
Guide to Linux jq Command for JSON Processing | Baeldung on Linux
August 31, 2025 - Note that in these two examples, we’ve constructed a new array, using [] around the array iteration. This contains only the prices before we pass this new list to the min or max function. The select function is another impressive utility that we can use for querying JSON. We can think of it as a bit like a simple version of XPath for JSON: ... This selects all the fruit with a price greater than 0.5. Likewise, we can also make selections based on the value of a property: ... $ jq '.[] | to_entries[] | select(.key | startswith("name")) | .value' fruits.json "apple" "banana" "kiwi"
Find elsewhere
Top answer
1 of 5
33

We can solve this problem by two ways. They are:

Input string:

// test.json
{
    "keys": ["key1","key2","key3"]
}

Approach 1:

1) Use jq -r (output raw strings, not JSON texts) .

KEYS=$(jq -r '.keys' test.json)
echo $KEYS
# Output: [ "key1", "key2", "key3" ]

2) Use @sh (Converts input string to a series of space-separated strings). It removes square brackets[], comma(,) from the string.

KEYS=$(<test.json jq -r '.keys | @sh')
echo $KEYS
# Output: 'key1' 'key2' 'key3'

3) Using tr to remove single quotes from the string output. To delete specific characters use the -d option in tr.

KEYS=$((<test.json jq -r '.keys | @sh')| tr -d \') 
echo $KEYS
# Output: key1 key2 key3

4) We can convert the comma-separated string to the array by placing our string output in a round bracket(). It also called compound Assignment, where we declare the array with a bunch of values.

ARRAYNAME=(value1 value2  .... valueN)
#!/bin/bash
KEYS=($((<test.json jq -r '.keys | @sh') | tr -d \'\"))

echo "Array size: " ${#KEYS[@]}
echo "Array elements: "${KEYS[@]}

# Output: 
# Array size:  3
# Array elements: key1 key2 key3

Approach 2:

1) Use jq -r to get the string output, then use tr to delete characters like square brackets, double quotes and comma.

#!/bin/bash
KEYS=$(jq -r '.keys' test.json  | tr -d '[],"')
echo $KEYS

# Output: key1 key2 key3

2) Then we can convert the comma-separated string to the array by placing our string output in a round bracket().

#!/bin/bash
KEYS=($(jq -r '.keys' test.json  | tr -d '[]," '))

echo "Array size: " ${#KEYS[@]}
echo "Array elements: "${KEYS[@]}

# Output:
# Array size:  3
# Array elements: key1 key2 key3
2 of 5
16

To correctly parse values that may have newlines (and any other arbitrary (non-NUL) characters) use jq's @sh filter to generate space-separated quoted strings, and Bash's declare -a to parse the quoted strings as array elements. (No pre-processing required)

foo.json:

{"data": ["$0", " \t\n", "*", "\"", ""]}
str=$(jq -r '.data | @sh' foo.json)
declare -a arr="($str)"   # must be quoted like this
declare -p arr
# declare -a arr=([0]="\$0" [1]=$' \t\n' [2]="*" [3]="\"" [4]="")

Update: jq 1.7 (2023-09)

As of version 1.7, jq has a --raw-output0 option, enabling it to output null-terminated strings which can be read into an array as usual:

mapfile -d '' arr < <(jq --raw-output0 '.data[]' foo.json)
wait "$!"  # use in bash-4.4+ to get exit status of the process substitution

Note on NUL characters in JSON strings

JSON strings may contain NUL characters while shell variables cannot. If your JSON input may contain NUL's, you may need to add some special handling.

  • When using the @sh filter, NUL characters from JSON strings will be silently replaced with the sequence \0. Note that this makes the JSON strings "\\0" and "\u0000" indistinguishable.

  • When using the --raw-output0 option, NUL characters will trigger an error and jq will terminate with an exit status of 5.

Reading multiple/nested arrays

The @sh filter can be combined with --raw-output0 to reliably read multiple arrays at once (or a single nested array) as it will produce a NUL-separated list of space-separated quoted strings.

json='[[1,2],[3,4]]' i=0
while read -r -d ''; do
    declare -a "arr$((i++))=($REPLY)"
done < <(jq --raw-output0 '.[]|@sh' <<<$json)
for ((n=0; n<i; n++)); { declare -p "arr$n"; }
# declare -a arr0=([0]="1" [1]="2")
# declare -a arr1=([0]="3" [1]="4")
Top answer
1 of 6
36

Using jq :

readarray arr < <(jq '.[].item2' json)
printf '%s\n' "${arr[@]}"

If you need a more hardened way:

readarray -td '' arr

for inputs with newlines or other special characters, avoiding word splitting.

Output:

value2
value2_2

Check:

Process Substitution >(command ...) or <(...) is replaced by a temporary filename. Writing or reading that file causes bytes to get piped to the command inside. Often used in combination with file redirection: cmd1 2> >(cmd2). See http://mywiki.wooledge.org/ProcessSubstitution http://mywiki.wooledge.org/BashFAQ/024

2 of 6
9

The following is actually buggy:

# BAD: Output line of * is replaced with list of local files; can't deal with whitespace
arr=( $( curl -k "$url" | jq -r '.[].item2' ) )

If you have bash 4.4 or newer, a best-of-all-worlds option is available:

# BEST: Supports bash 4.4+, with failure detection and newlines in data
{ readarray -t -d '' arr && wait "$!"; } < <(
  set -o pipefail
  curl --fail -k "$url" | jq -j '.[].item2 | (., "\u0000")'
)

...whereas with bash 4.0, you can have terseness at the cost of failure detection and literal newline support:

# OK (with bash 4.0), but can't detect failure and doesn't support values with newlines
readarray -t arr < <(curl -k "$url" | jq -r '.[].item2' )

...or bash 3.x compatibility and failure detection, but without newline support:

# OK: Supports bash 3.x; no support for newlines in values, but can detect failures
IFS=$'\n' read -r -d '' -a arr < <(
  set -o pipefail
  curl --fail -k "$url" | jq -r '.[].item2' && printf '\0'
)

...or bash 3.x compatibility and newline support, but without failure detection:

# OK: Supports bash 3.x and supports newlines in values; does not detect failures
arr=( )
while IFS= read -r -d '' item; do
  arr+=( "$item" )
done < <(curl --fail -k "$url" | jq -j '.[] | (.item2, "\u0000")')
🌐
O'Reilly
oreilly.com › library › view › jq-command-tutorials › 9781804610022 › video12_1.html
Creating Bash Array from JSON Array - Jq Command Tutorials for Bash Shell Scripting [Video]
July 6, 2022 - In this 2-hour course, you will master using the Jq command to efficiently handle JSON data within Bash shell scripts. You'll learn practical JSON manipulation techniques, including... - Selection from Jq Command Tutorials for Bash Shell Scripting [Video]
🌐
Reddit
reddit.com › r/bash › convert bash array to json with jq
r/bash on Reddit: Convert bash array to JSON with jq
May 2, 2020 -

I am writing a bash script for an Alfred Workflow. In this script I get a list (separated with newlines) from a command that I want to convert into a specific JSON format.

I tried storing the output into an array and parsing that in jq like that:

Command output:

$ piactl get regions

auto
france
netherlands

Create array:

$ IFS=$'\n'
$ regions=($(piactl get regions)) 
$ echo "${regions[@]}"

auto france netherlands

Parse to jq

$ jq -n --arg inarr "${regions}" '{ items: $inarr | split("\n") }'

{
  "items": [
    "auto"
  ]
}

jq only outputs one item of the array and I don't know how to shape the JSON like shown in the wanted output below.

Wanted output:

{"items": [
    {
        "title": "auto",
        "arg": "auto",
        "icon": {
            "path": "icon.png"
        }
    },
    {
        "title": "france",
        "arg": "france",
        "icon": {
            "path": "icon.png"
        }
    },
    {
        "title": "netherlands",
        "arg": "netherlands",
        "icon": {
            "path": "icon.png"
        }
    },
]}

Can somebody help me craft the correct jq arguments for this task?

🌐
Eliatra
eliatra.com › home › blog › transform json data on bash using jq
Transform JSON Data on Bash Using jq
November 23, 2022 - Since we grouped by Department, it does not matter from which object we take it for each array index. We just grab it from the first. For getting the number of employees for each Department, we just apply the length function. This example also shows how we can create an entire new JSON structure as output, and reference values from the step before: ... $ cat staff.json | jq 'group_by (.Department)[] | {Department: .[0].Department, length: length}' { "Department": "IT", "length": 2 } { "Department": "Management", "length": 1 }
🌐
Ingernet
ingernet.github.io › bash › jq › json › 2020 › 04 › 16 › json-array-bash-array.html
Converting a JSON array to a bash array
April 16, 2020 - # using gcloud output as a source because why not use the hardest shit possible bork=$(gcloud --project=<project-id> container images list-tags us.gcr.io/<project-id>/<image-name> --filter='tags:DEPLOYED' --format=json | jq '.[0].tags') echo $bork [ "260", "61a1d7aef75421f5c209c42304716ba44e86ab7a", "DEPLOYED.2019-11-12T17.04.37.772145800Z", "DEPLOYED.2019-11-13T00.00.29.525908800Z" ] # ^ output is obviously not a bash array # strip out all the things you don't want - square brackets and commas borkstring=$(echo $bork | sed -e 's/\[ //g' -e 's/\ ]//g' -e 's/\,//g') arr=( $borkstring ) echo $arr ( "260" "61a1d7aef75421f5c209c42304716ba44e86ab7a" "DEPLOYED.2019-11-12T17.04.37.772145800Z" "DEPLOYED.2019-11-13T00.00.29.525908800Z" ) # ^ now THAT is a bash array
🌐
Alfred App Community
alfredforum.com › alfred workflows › workflow help & questions
Construct script filter JSON with jq from bash array - Workflow Help & Questions - Alfred App Community Forum
January 30, 2022 - Hi, I am creating a workflow and I want to create a script filter with strings from a bash array. Given I have an array called $regions that contains 3 strings. I want to create 3 list items from that using jq. echo $regions france netherlands denmark I tried this command but the output is obviou...
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}]'
🌐
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"]
🌐
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} ]'