jq recipes: 23 one-liners for JSON on the command line
A runnable collection of jq filters for everyday JSON work: pick fields, filter with select, reshape, sort, count, group, pass shell variables, and export CSV.
Drafted with AI from official documentation. Scripts were run in a test environment and repository links verified. Awaiting a human check. Did it work for you? Last edited Outdated?
What this changes
Read-only: it runs jq on built-in sample JSON and prints the results; nothing on your system is changed. The optional install commands add the jq package.
How to undo it
Nothing to undo for the script. To remove jq again: brew uninstall jq, sudo apt remove jq or winget uninstall jqlang.jq.
jq is a small command-line program that reads JSON, applies a filter, and prints the result. This script runs each recipe against a built-in sample and prints the command next to its output, so you can see exactly what each filter does.
Install jq
Check before you run this
- Runs with administrator rights. Make sure you understand every line.
brew install jq # macOS (Homebrew)
sudo apt install jq # Debian, Ubuntu
winget install jqlang.jq # Windows
The basics in one minute
.is the whole input,.nameis a field,.users[0]is the first array element, and.users[]outputs each element separately.|passes the output of one filter into the next, like a shell pipe.- Wrap a filter in
[ ... ]to collect its outputs into one array. -rprints strings without quotes, which is useful in shell scripts.-cprints each result on one line.- Put the filter in single quotes so the shell does not interpret
$,|or[].
curl -s https://api.github.com/repos/jqlang/jq | jq '.stargazers_count'
jq -r '.users[].email' users.json
The script
Save it as jq-recipes.sh, then run bash jq-recipes.sh. To try a recipe on your own data, copy the filter and run jq '<filter>' yourfile.json.
#!/usr/bin/env bash
set -euo pipefail
command -v jq >/dev/null || { echo "jq is not installed" >&2; exit 1; }
SAMPLE='{
"store": "demo",
"users": [
{"id": 1, "name": "Ada", "email": "[email protected]", "tags": ["admin", "dev"], "active": true, "orders": 3},
{"id": 2, "name": "Brian", "email": null, "tags": ["dev"], "active": false, "orders": 0},
{"id": 3, "name": "Chen", "email": "[email protected]", "tags": [], "active": true, "orders": 5}
]
}'
run() {
local title=$1; shift
local shown="jq" arg
for arg in "$@"; do
if [[ $arg == -* ]]; then shown+=" $arg"; else shown+=" '$arg'"; fi
done
printf '\n### %s\n$ %s\n' "$title" "$shown"
printf '%s\n' "$SAMPLE" | jq "$@"
}
run "Pretty-print" '.'
run "One field" '.store'
run "Raw string, no quotes" -r '.store'
run "Every element of an array" '.users[]'
run "One field from each element" -r '.users[].name'
run "First and last element" '.users[0], .users[-1]'
run "Count elements" '.users | length'
run "Filter with select" '.users[] | select(.active)'
run "Filter by a number" -c '.users[] | select(.orders >= 3) | {name, orders}'
run "Keep results as an array" -c '[.users[] | select(.active) | .name]'
run "Reshape objects" -c '.users | map({id, contact: .email})'
run "Default for null" -r '.users[] | .email // "no email"'
run "Array contains a value" -r '.users[] | select(.tags | index("admin")) | .name'
run "Sort and take top N" -c '.users | sort_by(-.orders) | .[:2] | map(.name)'
run "Sum a field" '[.users[].orders] | add'
run "Group and count" -c '[.users[].tags[]] | group_by(.) | map({tag: .[0], count: length})'
run "List keys" -c '.users[0] | keys'
run "Add or change a field" -c '.users[0] | .vip = true | del(.tags)'
run "Use a shell variable safely" -c --arg who "Chen" '.users[] | select(.name == $who)'
run "Objects to CSV" -r '.users[] | [.id, .name, (.email // "")] | @csv'
run "Objects to TSV" -r '.users[] | [.id, .name] | @tsv'
run "Compact one line per item (JSON Lines)" -c '.users[]'
run "Find every key path" -c '[paths(scalars)] | .[:4]'
Sample output
### Group and count
$ jq -c '[.users[].tags[]] | group_by(.) | map({tag: .[0], count: length})'
[{"tag":"admin","count":1},{"tag":"dev","count":2}]
Notes
select(cond)passes an input through only when the condition is true.map(f)is shorthand for[.[] | f].a // breturnsbwhenaisnullorfalse. It is handy for defaults, but remember thatfalseis replaced too.- Never paste shell variables into the filter string. Pass them with
--arg name value(always a string) or--argjson name 42(parsed as JSON), then use$name. @csvneeds an array of simple values and quotes strings for you.@tsvescapes tabs and line breaks.- jq never edits a file in place. Write to a temporary file and move it:
jq '.version = "2"' app.json > tmp.json && mv tmp.json app.json. Redirecting straight back toapp.jsonempties it before jq reads it. - For JSON Lines input, jq already processes each object in turn. Add
-s(slurp) to read them all into one array first.
Did this work for you?
No votes yet. Be the first.
If it did not work, the report form below tells the editors what went wrong.
See also
- 0057 Shell cheat sheet: everyday commands A quick reference for moving around, managing files, viewing and searching text, checking processes and disk space in bash and zsh, with… Beginner · Cheat sheet · Linux, macOS Article Basics · Command-line tools 15 Oct 2026
- 0392 Install Visual Studio Code on Linux, macOS and Windows Install VS Code from Microsoft's packages, Homebrew or winget, get the code command working in the terminal, and add the extensions you… Beginner · Step by step · Linux, macOS, Windows Article Command-line tools · Installing languages & tools 15 Oct 2026
- 0421 grep, sed, awk and jq: the four text tools you will use every week A working reference for the four commands that handle most text on the command line: grep finds lines, sed edits them, awk… Intermediate · Cheat sheet · Linux, macOS Article jq & JSON on the command line · Modern command-line tools · Text processing 15 Oct 2026
- 0425 jq cheat script: pretty-print, filter and flatten JSON from a file or stdin A small read-only bash wrapper around jq with the recipes you keep looking up: pretty, compact, sorted keys, list paths, pick fields,… Beginner · Cheat sheet · Linux, macOS Script jq & JSON on the command line · Modern command-line tools · Text processing 15 Oct 2026
Repos in the wild
- ripgrep (rg): fast recursive search BurntSushi/ripgrep ripgrep is a line-oriented search tool that recursively searches the current directory for a regex pattern, skipping ignored, hidden and binary files by default. GitHub
- fzf: command-line fuzzy finder junegunn/fzf fzf is an interactive fuzzy finder for the terminal. Pipe any list into it, type a few letters, and pick the item you want. GitHub
- jq: command-line JSON processor jqlang/jq jq is a small command-line tool for reading, filtering and transforming JSON, like sed and awk for structured data. GitHub
- ShellCheck: static analysis for shell scripts koalaman/shellcheck ShellCheck reads your bash or sh scripts and points out bugs, quoting mistakes and portability problems before you run them. GitHub
History
Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.
- Dominik +5,234 chars