Sometimes you just want to read a JSON config file from Bash and iterate over an array. For example, when seeding some credentials to a credential store. This sometimes can be tricky especially when the JSON contains multi-line strings (for example certificates).

In this blog post I will explain how this can be done with jq and a Bash for loop.

First we will start with some data:

sample='[{"name":"foo"},{"name":"bar"}]'
echo "${sample}" | jq '.'
[
  {
    "name": "foo"
  },
  {
    "name": "bar"
  }
]

By using jq --compact-output (or -c) we can get each object on a newline.

sample='[{"name":"foo"},{"name":"bar"}]'
echo "${sample}" | jq -c '.[]'
{"name":"foo"}
{"name":"bar"}

We could start iterating of the above with a Bash for loop if our data does not contain spaces or newlines. But since certificates contain newlines we better base64 encode each line. Also, instead of -c, we now use -r to get rid of the extra quotes.

sample='[{"name":"foo"},{"name":"bar"}]'
echo "${sample}" | jq -r '.[] | @base64'
eyJuYW1lIjoiZm9vIn0=
eyJuYW1lIjoiYmFyIn0=

Now let's build our for loop.

sample='[{"name":"foo"},{"name":"bar"}]'
for row in $(echo "${sample}" | jq -r '.[] | @base64'); do
    _jq() {
     echo ${row} | base64 --decode | jq -r ${1}
    }

   echo $(_jq '.name')
done
foo
bar