jq — Working with JSON
APIs, cloud tools and config files speak JSON. grep and awk see it as lines of text; jq understands it.
It isn't installed on a fresh Debian:
sudo apt install jq
Your server inventory for this lesson is in ~/json/servers.json.
Pretty-print and pick
jq . ~/json/servers.json # the whole file, indented
jq .updated ~/json/servers.json # one field
jq '.servers[0]' ~/json/servers.json # the first server
jq '.servers[0].ip' ~/json/servers.json # a field of it
. is "the input". .servers takes a field, [0] an element of an array ([-1] is the last).
Always put the filter in single quotes — [, | and " mean something to the shell too.
Every element: .[]
jq '.servers[].name' ~/json/servers.json # "web01" "web02" ...
jq -r '.servers[].name' ~/json/servers.json # -r: raw text, no quotes
-r is what you want when the output goes on to grep, while read or a file.
Pipes inside jq
| passes each result on, like in the shell:
jq '.servers | length' ~/json/servers.json # how many
jq '.servers[] | select(.status == "stopped") | .name' ~/json/servers.json
jq '[.servers[].ram_gb] | add' ~/json/servers.json # total RAM
select(CONDITION)keeps only what matches —==,!=,>,and,orwork as you'd expect[ ... ]collects results into an array;addsums it,lengthcounts it
Your own shape
jq '.servers[] | {name, ip}' ~/json/servers.json # just these fields
jq -c '.servers[] | {name, ram: .ram_gb}' ~/json/servers.json # -c: one line each
jq -r '.servers[] | "\(.name) has \(.ram_gb) GB"' ~/json/servers.json
\( … ) puts a value into a string.
Into a spreadsheet: @csv
jq -r '.servers[] | [.name, .ip, .status] | @csv' ~/json/servers.json
"web01","10.0.0.11","running"
"web02","10.0.0.12","stopped"
Straight from an API
curl -s + jq is the everyday pair:
curl -s https://api.example.com/servers | jq '.servers[] | select(.status != "running") | .name'
| Filter | Does |
|---|---|
.a.b | field b of field a |
.[0], .[-1] | first / last element |
.[] | every element |
select(...) | keep what matches |
map(...) | change every element of an array |
length, add, keys | count, sum, field names |
sort_by(.x), group_by(.x) | order, group |
💡
jq -r+@csvturns any JSON into somethingsort,awkor a spreadsheet can read.