If my sed cheat sheet was for text, this one is for JSON. jq is the tool I reach for whenever an API, a kubectl command, or a config file hands me more JSON than I want to read.
All examples use this file, data.json:
{"users":[
{"name":"Ada","role":"admin","tags":["a","b"]},
{"name":"Linus","role":"dev","tags":[]}
]}
Pretty print and pick a field
jq . data.json
jq '.users[].name' data.json
The first prints the whole document with indentation. The second walks every item in users and prints each name. Add -r to drop the quotes around strings.
Filter with select
jq '.users[] | select(.role == "admin")' data.json
select keeps only the items where the condition is true. Pipes (|) work like they do in the shell: the output of the left side feeds the right side.
Build a new array or object
jq '[.users[].name]' data.json
jq '.users | map({name, role})' data.json
Wrapping an expression in [ ] collects the results into an array. map applies an expression to every element, and {name, role} is shorthand for {name: .name, role: .role}.
Count, join, and group
jq '.users | length' data.json
jq -r '.users | map(.name) | join(", ")' data.json
jq '.users | group_by(.role) | map({role: .[0].role, count: length})' data.json
Defaults for missing values
jq '.users[0].email // "none"' data.json
The // operator returns the right side when the left is null or missing.
Output for other tools
jq -r '.users[] | [.name, .role] | @csv' data.json
@csv, @tsv, and @sh format arrays for spreadsheets and shell scripts. Pair them with -r so you don’t get escaped quotes.
Update values
jq '.users |= map(.name |= ascii_upcase)' data.json
|= updates a value in place and returns the whole document, so you can redirect it to a new file.
Pass shell variables safely
jq -n --arg name "Ada" '{name: $name}'
Use --arg instead of string-interpolating shell variables into the filter. It handles quoting for you.
A real-world one-liner
kubectl get pods -o json | jq -r '.items[] | select(.status.phase != "Running") | .metadata.name'
That lists every pod that isn’t running. Once the pattern clicks, you’ll start piping everything into jq.
