Which command to use
| Tool | Command | Indent | Comes with |
|---|---|---|---|
| jq | jq . order.json |
2 spaces | macOS 15 and later |
| Python | python3 -m json.tool order.json |
4 spaces | Python |
| Node.js | node -p "JSON.stringify(require('./order.json'), null, 2)" |
your choice | Node.js |
| PowerShell | Get-Content order.json -Raw | ConvertFrom-Json | ConvertTo-Json -Depth 100 |
2 spaces (7.x), wide (5.1) | Windows |
json_pp < order.json, which comes with Perl, is often installed on macOS and Linux too. It indents with 3 spaces.
Pretty print JSON on the command line with jq
Install it if jq --version finds nothing:
brew install jq
sudo apt-get install jq
sudo dnf install jq
winget install jqlang.jq
These are for macOS (Homebrew), Debian and Ubuntu, Fedora, and Windows. Then pass the file and ., the filter that outputs its input unchanged:
jq . order.json
{
"order": "B-77",
"status": "shipped",
"lines": [
{
"sku": "LAMP-3",
"qty": 2
},
{
"sku": "BULB-9",
"qty": 6
}
],
"notes": null
}
jq -S . order.json
jq --indent 4 . order.json
jq --tab . order.json
jq -c . order.json
jq -C . order.json | less -R
-S sorts keys, --indent takes up to 7 spaces, --tab indents with tabs and -c puts everything on one line. jq colors its output in a terminal; -C keeps the color through a pipe for less -R.
Invalid input stops with a position, for example jq: parse error: Expected another key-value pair at line 1, column 29 for a trailing comma.
Python and Node.js
python3 -m json.tool order.json
python3 -m json.tool --indent 2 --sort-keys order.json
node -p "JSON.stringify(JSON.parse(require('fs').readFileSync(0, 'utf8')), null, 2)" < order.json
On Windows, type py or python instead of python3. Python 3.14 and later also accept python -m json. Every flag is in pretty print JSON in Python, and replacers and key sorting in pretty print JSON in JavaScript.
PowerShell
Get-Content shipment.json -Raw | ConvertFrom-Json | ConvertTo-Json -Depth 100
Always pass -Depth. The default is 2, and deeper objects turn into strings. Windows PowerShell 5.1 does this without a warning:
{
"order": "B-77",
"ship": {
"to": {
"city": "Leeds",
"geo": "@{lat=53.8; lon=-1.55}"
}
}
}
PowerShell 7.1 and later cut it the same way but print a warning. Other differences in Windows PowerShell 5.1:
- The indentation is wide, as above, and
<,>,'and&are written as\u003c,\u003e,\u0027and\u0026. Get-Contentreads BOM-less UTF-8 as the ANSI code page, soSão PaulobecomesSão Paulo. Add-Encoding UTF8.
In PowerShell 7, [1] comes back as 1 unless you add -NoEnumerate to ConvertFrom-Json, and ISO timestamps become DateTime values unless you add -DateKind String (7.5 and later).
Pretty print curl output
curl -s https://api.github.com/repos/jqlang/jq | jq .
curl -s https://api.github.com/repos/jqlang/jq | jq '{name, stars: .stargazers_count}'
-s hides curl’s progress meter. The second filter keeps two fields and renames one. In Windows PowerShell 5.1, curl is an alias for Invoke-WebRequest, so type curl.exe, or use Invoke-RestMethod URL | ConvertTo-Json -Depth 100.
Decode a JWT payload with jq
A JWT is three base64url parts separated by dots, and the middle one is the payload:
TOKEN='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTQ4MjEiLCJuYW1lIjoiTWlhIENoZW4iLCJhdWQiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbS8_dj0yIiwicm9sZSI6ImVkaXRvciIsImlhdCI6MTc5MzgwMDAwMCwiZXhwIjoxNzkzODAzNjAwfQ.j37yaZ5oSIjQgIT53XzXhPhVLSR0b_Vkmsl8Pss1HM8'
jq -R 'split(".")[1] | gsub("-"; "+") | gsub("_"; "/") | @base64d | fromjson' <<< "$TOKEN"
{
"sub": "user-4821",
"name": "Mia Chen",
"aud": "https://api.example.com/?v=2",
"role": "editor",
"iat": 1793800000,
"exp": 1793803600
}
The two gsub calls turn base64url into the standard alphabet. Without them, a token containing _ or - fails with jq: error (at <stdin>:1): string ("eyJzdWIiOi...") is not valid base64 data. Missing = padding is fine. Add | .exp | todate to read the expiry as a date. On Windows, where <<< does not exist, save the filter as jwt.jq and the token as token.txt, then run jq -R -f jwt.jq token.txt. This decodes only; it does not verify the signature. The JWT decoder does the same in the browser and shows whether exp has passed.
Windows quoting and encoding
- cmd has no single quotes. Wrap the filter in double quotes and escape inner ones:
jq ".lines[] | select(.sku == \"LAMP-3\")" order.json. - Windows PowerShell 5.1 strips double quotes inside arguments, so
jq '.lines[] | select(.sku == "LAMP-3")' order.jsonfails withjq: error: LAMP/0 is not defined. Fix it with\"LAMP-3\", with a filter file (jq -f filter.jq order.json), or with PowerShell 7.3 or later, which passes the quotes through. - Piping in Windows PowerShell 5.1 (
Get-Content order.json | jq .) sends text as US-ASCII, so accented letters arrive as?. Pass the file name to jq or Python instead.
To pretty print without a terminal, paste the JSON into JSON Prettier. Editor and language guides are in JSON guides.