Format (pretty-print) JSON from a shell
Pretty-print a JSON blob from a curl response, log line, or config file — for human-readable inspection or diffing.
How to format (pretty-print) json from a shell in each shell
echo '{"a":1,"b":[2,3]}' | jq .`jq .` (literal dot) is the identity filter — pretty-prints + colourises. Without jq installed: `python3 -m json.tool` is the universal fallback (every Linux/macOS box with Python). Or `python3 -c "import json,sys; print(json.dumps(json.load(sys.stdin), indent=2))"`. For minified output: `jq -c .` (one line, no whitespace). For specific fields: `jq '.users[0].email'` (the powerful query language is jq's real superpower; `.` alone undersells it).
echo '{"a":1,"b":[2,3]}' | jq .Same external. Install: `brew install jq` (macOS), `apt install jq` (Debian/Ubuntu), `apk add jq` (Alpine). For richer JSON tools: `gron` flattens JSON to grep-able `key.path = value` form; `jaq` is a faster Rust rewrite of jq with the same query language; `yq` extends jq syntax to YAML/TOML/XML.
echo '{"a":1,"b":[2,3]}' | jq .Same external. Fish quoting nuance: fish doesn't require backslash-escaping inside single-quoted strings, so `'{"a":1}'` works as written. For multi-line JSON input: `cat file.json | jq .`. For "extract a field and use it as a variable": `set name (curl -s api.example.com/me | jq -r .name)` — `-r` is "raw output" (strips JSON quotes, so you don't get `"alice"` with the quotes).
'{"a":1,"b":[2,3]}' | ConvertFrom-Json | ConvertTo-Json -Depth 10Built-in — no external tool needed. `-Depth 10` is critical: `ConvertTo-Json` defaults to `-Depth 2` and SILENTLY TRUNCATES deeper nesting to the string `System.Collections.Hashtable`. Always pass `-Depth 10` (or larger) for unknown input. For minified: `ConvertTo-Json -Compress`. For "query a field" (the jq equivalent): `(ConvertFrom-Json $json).users[0].email` — works because JSON parses to nested pwsh objects with normal `.field` access.
powershell -NoProfile -Command "'{\"a\":1}' | ConvertFrom-Json | ConvertTo-Json -Depth 10"cmd has NO native JSON tooling. Shell out to pwsh (above), watching cmd's nightmare quote-escaping (double-quotes inside double-quotes need `\"`). If jq is installed on the Windows box (via `winget install jqlang.jq` or scoop): `echo {"a":1} | jq .` works in cmd too. For a one-time pretty-print, the simplest path is "paste into pwsh".
Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.
Gotchas & notes
- pwsh `ConvertTo-Json -Depth` default of 2 is the source of countless silent-data-loss bugs. ANY production script that re-serializes a parsed JSON object MUST set `-Depth` explicitly. Test: `'{"a":{"b":{"c":1}}}' | ConvertFrom-Json | ConvertTo-Json` produces `"c"` as a string `"@{c=1}"` — visible corruption. With `-Depth 10` it round-trips cleanly.
- jq's query syntax is a small DSL worth learning if you grep JSON daily. Common patterns: `.users[] | .email` (extract one field across an array), `.users | length` (count), `.users[] | select(.active == true)` (filter), `[.users[] | .age] | add / length` (average). All work on streaming input.
- For COMPARING two JSON files (a common need), pretty-print BOTH first then diff: `diff <(jq -S . a.json) <(jq -S . b.json)`. The `-S` sorts keys alphabetically — without it, two JSONs that differ only by key order show as different. pwsh equivalent: `(Get-Content a.json | ConvertFrom-Json | ConvertTo-Json -Depth 10) -eq (Get-Content b.json | ConvertFrom-Json | ConvertTo-Json -Depth 10)` (but ConvertTo-Json doesn't sort keys — sort manually if needed).
- For huge JSON files (multi-GB log dumps), `jq` reads the whole file into memory. Streaming alternatives: `jq --stream` emits paths+values as a flat stream; `jstream` (Go) parses JSON arrays element-by-element. Or split the file with `jq -c '.records[]'` first into one-object-per-line, then process with line-oriented tools.
Related commands
Related tasks
- Encode a string to base64— Convert a string (or file) to its base64 representation — for HTTP basic auth headers, JWT payloads, embedded credentials in YAML, or any text-only transport of binary.
- Download a file from a URL— Save a remote file to disk via HTTP/HTTPS, with progress and resume where supported.