jq

The jq utility helps parsing, and modifying JSON structures.

Install

curl \
   --silent \
   --url https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 \
   --location \
   --output ./jq

chmod +x ./jq
sudo mv ./jq /usr/local/bin
sudo chown root.root /usr/local/bin/jq

When I neet to create a larger JSON structure in a shell script, I don't like the approach of creating a honking big string:

#!/bin/bash

someVar1="Something something"
someVar2="something else"

# Create a large JSON string, not very maintainable
json1="{\"v1\":\"${someVar1}\",\"v2\": \"${someVar2}\"}"
echo  "${json1}" | jq .

Instead, I prefer a step-by-step creation process. Below, we're starting with an empty JSON object ("{}"), and piping it through a bunch of jq calls. In such a call, we bind the shell variable's value to the jq variable x, and set the value on the fly:

#!/bin/bash

someVar1="Something something"
someVar2="something else"

# Create a large JSON string, not very maintainable
json="$( echo "{}" \
  | jq --arg x "${someVar1}" '.v1=$x' \
  | jq --arg x "${someVar2}" '.v2=$x' \
)"
echo  "${json}" | jq .

This outputs

{
  "v1": "Something something",
  "v2": "something else"
}

Alternatively, try this:

#!/bin/bash

someVar1="Something something"
someVar2="true"

# Create JSON step-by-step
json="$( echo "{}" \
  | jq --arg x "${someVar1}" '.v1=$x' \
  | jq --arg x "${someVar2}" '.trueAsAString=$x' \
  | jq --arg x "${someVar2}" '.trueAsABoolean=($x | fromjson)' \
  | jq '.someArray=[]' \
)"

#
# Now let's add a bash array to the JSON structure, element by element
#
allThreads=(1 2  '"hi"' "true" false '{}')

for t in ${allThreads[@]}; do
  json="$( echo "${json}" | jq  --arg xx "${t}" '.someArray[.someArray | length] |= .+ ($xx | fromjson)' )"
done

echo  "${json}" | jq .

Which gives

{
  "v1": "Something something",
  "trueAsAString": "true",
  "trueAsABoolean": true,
  "someArray": [ 1, 2, "hi", true, false, {} ]
}

Incrementally adding to an array in JQ

#!/bin/bash

x="$( echo "{}" | jq ".x=[]" )"
x="$( echo "${x}" | jq ".x[.x | length] |= .+ \"foo\"" )"
x="$( echo "${x}" | jq ".x[.x | length] |= .+ 1"       )"
x="$( echo "${x}" | jq ".x[.x | length] |= .+ true"    )"
echo "${x}"

results in

{ "x": [ "foo", 1, true ] }

Forgot what I did here...

#!/bin/bash

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

Crack up the claims part of a JWT

#!/bin/bash

access_token="eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtleTEifQ.eyJpc3MiOiJodHRwczovL2NoZ2V1ZXIuYmxvYi5jb3JlLndpbmRvd3MubmV0L3B1YmxpYyIsImF1ZCI6ImFwaTovL0F6dXJlQURUb2tlbkV4Y2hhbmdlIiwic3ViIjoic3ViamVjdCIsImlhdCI6MTY0NDQ0NjQzNSwiZXhwIjoxNjQ0NDQ3MDM1fQ.GG1n7B81D8HZIvCS2e-bWzomMRyqMb-zs-8oF2Oh_dgIQy2TT15DoJaBZrybsMvRRjfJbsmQz_Pay1dFSwtfDMY4WF2MwxPk95VKz4f9MO4SA_NVY8lMHB49gosBqUpQrPD8DzKEIm-cvIpJJTQzNpcefoNf_Ax2AlbDy5h3zazlvqpFUjim-3nwCTN2ERd0FB3iTsTMMk6VG0bu76qkK-9t3Zh8tdkENCcLVQslHBkcFhN3F9hRLLYiEtOTyLTFaWSr0PDbsiSsMmK8XGxMHNF2K03LGk-whb0mPjKQ17mvclMLgJ9M187KC8HljAIj3Powtw9YsVp6kC2y"

claims="$( jq -R 'split(".") | .[1] | @base64d | fromjson' <<< "${access_token}" )"

echo "${claims}" | jq .

echo "${claims}" | jq .iss

Last updated