Pull a value out of JSON with jq '.users[0].name' api.json — the dot is jq's path syntax, and everything past it (select, @csv, -r) is the same idea applied to filtering, converting, or cleaning up the output. jq treats JSON the way awk treats text: parse once, then pipe filters together. The six patterns below cover what actually comes up when you're staring at an API response and need one field, a filtered list, or a CSV out of it.
1. Get one field
$ clai get the first user's name from api.json→ jq '.users[0].name' api.json"alice"
The dot is jq's filter for "take the current value," and a path follows it. The quotes in the output mean jq returned a JSON string, not plain text for the shell.
2. Strip quotes for scripting
$ clai print all user names without quotes→ jq -r '.users[].name' api.jsonalicebob
-r (raw output) gives you bare strings, which is what you want when the result feeds a shell variable or a loop. Skip -r and you get quoted strings that fail your first comparison for no obvious reason.
3. Filter by a condition
$ clai show the names of users older than 30→ jq -r '.users[] | select(.age > 30) | .name' api.jsonalice
.users[] unrolls the array into a stream of values, and select() only lets the matching ones through. The pipe inside jq works exactly like a shell pipe.
4. Turn it into CSV
$ clai turn this into csv with name and age→ jq -r '.users[] | [.name, .age] | @csv' api.json"alice",34"bob",28
Collect the fields you want into an array and hand it to @csv. There's also @tsv, @base64, and @uri. That's one line instead of a Python script.
5. Make sense of an unfamiliar API response
$ clai show what keys exist at the top level→ jq -r 'keys[]' api.jsonusers
This is the first thing worth running against someone else's JSON. Follow it with jq -r '.users[0] | keys[]' to see the fields inside one element.
6. Parse an API response straight from curl
$ clai get json from the api and print just the version field→ curl -s https://example.com/api/status | jq -r '.version'
This combination is the whole reason jq exists. -s turns off curl's progress meter — without it, that meter lands in the stream and jq chokes on it.
Gotchas
-rchanges the output, not the filter. A missing-ris behind most of the"1.2.3"-in-a-string-comparison weirdness in bash scripts.- A key with a dash or a dot needs quotes:
jq '."content-type"'. Without them jq tries to parse it as an expression and fails. - jq chokes on a stream of several JSON objects. For line-delimited JSON (JSON Lines), add
-s(slurp) or process it line by line.
Related questions
How do I get the last element of an array? jq '.users[-1]'. Negative indices count from the end.
How do I check whether a field exists? jq 'has("age")' on an object, or jq '.users[] | select(has("email"))' to filter a list.
jq or python -m json.tool? json.tool only formats. jq selects, filters, and transforms — different jobs in a pipeline.
See also
- Print a column from a CSV with awk (and when not to)
- Network triage in plain English
- From one-liner to checked-in script: when to graduate
Describe the field you need and CliAI writes the jq filter, quotes included. Install it in one line.