jq cheat sheet
| Filter | What it does |
|---|---|
. |
The whole input, pretty-printed |
.name |
Value of a key (null if missing) |
."first-name" |
A key with special characters |
.items[0] |
First element of an array; .items[-1] is the last |
.items[] |
Every element, one output each |
.items[2:5] |
A slice of an array or string |
.a, .b |
Both values, one after the other |
.items[] | .id |
Pipe: run the right side on each output of the left |
{id, name} |
Build an object from existing keys |
[.items[].id] |
Collect outputs into an array |
select(.age > 30) |
Keep the input only if the condition is true |
map(.price * 2) |
Transform each array element |
.x // "default" |
Fallback when .x is null or false |
length, keys, add |
Size, sorted keys, sum or concatenation |
sort_by(.age), group_by(.team), unique_by(.id) |
Sort, group and deduplicate arrays of objects |
to_entries, from_entries, with_entries(f) |
Convert between objects and [{key, value}] arrays |
del(.secret), .a.b = 1, .n += 1 |
Delete and update values |
"\(.name) is \(.age)" |
String interpolation |
@csv, @tsv, @json, @base64, @uri |
Format a value; use with -r for raw text |
$var |
A value passed with --arg var value or --argjson var json |
Command-line recipes
# Pretty-print an API response
curl -s https://api.github.com/repos/jqlang/jq | jq .
# Pull one field out of every item, as plain text
jq -r '.items[].metadata.name' pods.json
# Kubernetes: names of pods that aren't Running
kubectl get pods -o json | jq -r '.items[] | select(.status.phase != "Running") | .metadata.name'
# Turn JSON Lines into one array
jq -s '.' events.jsonl
# Use a shell variable safely (never paste it into the filter)
jq --arg user "$USER" '.users[] | select(.name == $user)' users.json
# Edit a file: jq has no in-place flag, so write to a temp file
jq '.version = "2.0.0"' package.json > tmp.json && mv tmp.json package.json
Mistakes that trip people up
Cannot index array with string
.users.name fails because .users is an array. Iterate first:
.users[].name, or .users | map(.name) to keep the result as an array.
Cannot iterate over null
A key is missing on some objects. Use .tags[]? to skip missing values, or provide a default with
(.tags // [])[].
Shell quoting
Wrap the filter in single quotes on macOS and Linux so the shell leaves $, | and double
quotes alone. In Windows cmd, use double quotes around the filter and escape the inner ones; PowerShell
users can put the filter in a file and run jq -f filter.jq.
Install jq
brew install jq # macOS
sudo apt install jq # Debian, Ubuntu
winget install jqlang.jq # Windows
jq --version
Only need to pick values out of a document? Try the JSONPath Tester. To explore an unfamiliar response first, open it in the JSON Viewer.
Frequently asked questions
Is this the real jq?
Yes. The playground runs jq 1.8 compiled to WebAssembly, so filters, built-in functions, error messages and output formatting behave exactly as on the command line. It runs in your browser; your JSON is not uploaded.
What is the difference between jq and JSONPath?
JSONPath only selects values. jq is a full language: besides selecting, it can build new objects, rename keys, group, sort, aggregate, do arithmetic and format output as CSV. If you only need to pick values out of a document, the JSONPath Tester is simpler.
How do I print strings without quotes?
Turn on Raw output (-r). jq then prints string results as plain text, which is what you want when the output goes to another shell command or a CSV file.
How do I process JSON Lines (one JSON value per line)?
Paste the lines as they are; jq runs the filter once per value. Turn on Slurp (-s) to read them all into a single array first, for example to count or sort them.
How do I pass a variable into a jq filter?
Click + Variable and give it a name and value, then use it as $name in the filter. It becomes --arg name value on the command line, or --argjson when the JSON box is ticked. This avoids quoting problems from pasting shell variables into the filter.
Why did my filter stop with a timeout?
Filters that never finish, such as repeat(.) or a recurse without a stop condition, are stopped after 3 seconds so the page stays responsive. Add a condition, or use limit(n; expr) to take only the first results.