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