Curl returns minified JSON. The terminal shows it as one long line. Five tools turn that into readable, queryable output — and once you know them, you'll reach for them constantly.
jq — the standard answer
jq is a small, fast JSON processor with its own query language. It's the closest thing to a Unix standard for JSON.
Install: brew install jq, apt install jq, or download from jqlang.org. It's a single static binary.
Pretty-print:
curl https://api.github.com/users/torvalds | jq
Yes, just jq with no filter. The default is to pretty-print with 2-space indentation. Colors are on for terminals, off for pipes.
Select fields:
curl https://api.github.com/users/torvalds | jq '{name, location, public_repos}'
Filter arrays:
curl https://api.github.com/users/torvalds/repos \
| jq '[.[] | select(.stargazers_count > 100) | .name]'
The [.[]] pattern is jq's "for each item in this array." select() is a predicate. The outer [] rewraps results into an array.
Convert to CSV/TSV:
jq -r '.[] | [.name, .stars, .lang] | @csv'
The -r flag means "raw output" — don't quote the string output as JSON. @csv, @tsv, and @sh are built-in formatters that handle quoting correctly.
python -m json.tool — when jq isn't installed
Python 3 ships with a JSON pretty-printer:
cat data.json | python3 -m json.tool
It's basic — no query language, no colors — but it's always there on macOS, Linux, and most servers. For one-off pretty-printing it does the job.
fx — interactive viewer
fx (npm install -g fx) opens a JSON document in an interactive tree browser. Arrow keys to navigate, . to type a JSONPath. Great for big documents you want to explore before writing a jq query.
cat huge-response.json | fx
jless — pager for JSON
jless is like less, but understands JSON. Folding, searching by key, jumping to errors. Written in Rust; fast on multi-megabyte files.
cat big.json | jless
j/k to scroll, Space to fold/unfold, /pattern to search. If your day involves reading large API dumps, install jless.
gron — grep-able JSON
gron flattens JSON into one assignment per line. Each line is a complete JavaScript-style path:
$ cat data.json | gron
json.name = "Alice";
json.address.city = "Seattle";
json.tags[0] = "admin";
json.tags[1] = "vip";
Now you can grep for specific paths or values — something jq's query language makes harder than it should be:
cat data.json | gron | grep '\.email ='
cat data.json | gron | grep '"admin"'
gron --ungron reverses the operation, so you can edit the flat form and rebuild the JSON. Useful for surgical edits.
Comparison table
| Tool | Best for | Install |
|---|---|---|
| jq | Filtering, transforming, scripting | brew/apt |
| python -m json.tool | One-off pretty-print, no install | built-in |
| fx | Interactive exploration of unknown JSON | npm |
| jless | Reading large files like less | brew/cargo |
| gron | Greppable output, surgical edits | brew/go |
Combine them
These tools compose. Common pipelines:
# Get every email from a paged response, sorted unique
cat users.json | jq -r '.data[].email' | sort -u
# Find all paths containing "password" (oops)
cat config.json | gron | grep -i password
# Pretty + page big responses
curl ... | jq | less -R
When the browser is faster
For ad-hoc exploration of a single JSON document you already have, the online formatter often beats any terminal tool — instant syntax highlighting, click to collapse sections, no learning curve. The terminal wins as soon as you want to run the same operation again or save it to a script.
Wrap-up
Learn jq first — the time investment pays off forever, and it's the lingua franca for shell-based JSON work. Add jless when you start dealing with large files. Reach for gron when jq's query syntax is getting in your way and you just want lines you can grep.