Yesterday we saw how to read key/value pairs from a JSON document and map them into a bash friendly format. Today we finish the job with a read/while loop.

A read/while loop is a simple bash construct that loops over input and maintains the integrity of each line. This is perfect for dealing with JSON key/value pairs.

As a reminder, here’s the output of our jq command:

jq -r ".widget.text|to_entries|map(\"\(.key)=\(.value)\")|.[]" < "example.json"

#=> data=Click Here
#=> size=36
#=> style=bold

The key is to pipe the jq output into a while loop, which is done by enclosing the jq command in a < <( ) syntax. Check out the basic implementation:

while read line; do
  echo $line
done < <(jq -r ".widget.text|to_entries|map(\"\(.key)=\(.value)\")|.[]" < "example.json")

#=> data=Click Here
#=> size=36
#=> style=bold

Great. We’re almost there. Now we just need to extract the key / value pairs. This is done by specifying the internal field separator or IFS, which is an internal bash variable that denotes the char which separates words. It defaults to a white space, but we can use any char we want. In this case we will use the = sign.

while IFS="=" read key value; do
  echo "key is '$key'"
  echo -e "value is '$value'\n"
done < <(jq -r ".widget.text|to_entries|map(\"\(.key)=\(.value)\")|.[]" < "example.json")

#=> key is 'data'
#=> value is 'Click Here'

#=> key is 'size'
#=> value is '36'

#=> key is 'style'
#=> value is 'bold'

This is awesome. We now have access to the JSON data as easily as if we were in a JavaScipt application. Now we can do whatever we need to do with the data. My recent use case was setting environmental variables:

while IFS="=" read key value; do
  export $key="$value"

  echo "env var '$key' is set to ${!key}"
done < <(jq -r ".widget.text|to_entries|map(\"\(.key)=\(.value)\")|.[]" < "example.json")

#=> env var 'data' is set to Click Here
#=> env var 'size' is set to 36
#=> env var 'style' is set to bold

Good stuff. With jq and a read while loop it becomes possible to make very robust bash scripts to accomplish many useful tasks.

Note: For a post about how I’m accessing the value of the env variable in that last example(${!key}), see this post