Skip to content
Advertisement

JSON list (not object) to Bash array?

I’ve got a JSON list (the value of a key-value pair containing a list of items):

[ "john", "boris", "joe", "frank" ]

How would I convert this to a bash array, so I can iterate over them?

Advertisement

Answer

Easy Case: Newline-Free Strings

The simple approach is to use jq to transform your list into a line-per-item, and read that into your script:

json='[ "john", "boris", "joe", "frank" ]'
readarray -t your_array < <(jq -r '.[]' <<<"$json")
declare -p your_array

…properly emits:

declare -a your_array=([0]="john" [1]="boris" [2]="joe" [3]="frank")

Tricky Case: Strings With Newlines

Sometimes you need to read strings that can contain newlines (or want to avoid security risks caused by malicious or malformed data being read into the wrong fields). To avoid that, you can use NUL delimiters between your data (and remove any NUL values contained therein):

json='[ "johnndoe", "marconquent", "maliciousu0000data" ]'

array=( )
while IFS= read -r -d '' item; do
  array+=( "$item" )
done < <(jq -j '.[] | ((. | sub("u0000"; "<NUL>")) + "u0000")' <<<"$json")

declare -p array

…properly emits:

declare -a array=([0]=$'johnndoe' [1]=$'marconquent' [2]="malicious<NUL>data")

…and printf '<%s>nn' "${array[@]}" properly emits:

<john
doe>

<marco
quent>

<malicious<NUL>data>

(Note that very new bash has readarray -0, which can avoid the need for the while IFS= read -r -d '' loop given above, but that’s not common yet. Also note that you can use that loop to directly iterate over content from jq, avoiding the need to store content in an array in the first place; see BashFAQ #1).

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement