The jq
utility helps parsing, and modifying JSON structures.
Install
Copy 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:
Copy #!/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:
Copy #!/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
Copy {
"v1" : "Something something" ,
"v2" : "something else"
}
Alternatively, try this:
Copy #!/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
Copy {
"v1" : "Something something" ,
"trueAsAString" : "true" ,
"trueAsABoolean" : true ,
"someArray" : [ 1 , 2 , "hi" , true , false , {} ]
}
Incrementally adding to an array in JQ
Copy #!/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
Copy { "x" : [ "foo" , 1 , true ] }
Forgot what I did here...
Copy #!/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
Copy #!/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