Pretty-print JSON with jq

jq . data.json

jq . data.json prints the file indented by two spaces, in color when the output is a terminal. . is jq’s identity filter: it passes the input through unchanged, and jq’s printer does the formatting. It reads from a pipe too: curl -s https://api.example.com/users/42 | jq ..

printf '%s' '{"name":"café","id":12345678901234567890,"tags":["api","ops"],"active":true,"manager":null}' > data.json
jq . data.json
{
  "name": "café",
  "id": 12345678901234567890,
  "tags": [
    "api",
    "ops"
  ],
  "active": true,
  "manager": null
}

That’s jq 1.7.1, and the formatter below prints the same for that text with 2 spaces.

The flags you’ll want

jq -S . data.json           # sort keys at every depth
jq -c . data.json           # minify: {"name":"café","id":12345678901234567890,...}
jq --indent 4 . data.json   # 4 spaces; jq allows at most 7
jq --tab . data.json        # tabs
jq -a . data.json           # escape non-ASCII: "caf\u00e9"
jq -r .name data.json       # one string, without quotes: café
jq empty data.json          # validate only: no output, non-zero exit if invalid

-S orders keys by code point and leaves arrays in their order, the same as Sort keys below. --indent 0 prints the same as -c.

Big numbers: check your version

jq 1.7 keeps the full precision of a number literal it doesn’t compute with, so the 20-digit id above survives. jq 1.6 converts every number to an IEEE 754 double first, and it’s still what Debian 12 and Ubuntu 22.04 install (Ubuntu 24.04 has 1.7.1). With nums.json holding {"price":1.10,"id":12345678901234567890,"big":1e1000,"exp":1e5}:

$ jq --version
jq-1.6
$ jq -c . nums.json
{"price":1.1,"id":12345678901234567000,"big":1.7976931348623157e+308,"exp":100000}

The same file through jq 1.7.1:

$ jq -c . nums.json
{"price":1.10,"id":12345678901234567890,"big":1E+1000,"exp":1E+5}

Even 1.7 rewrites exponents (1e5 becomes 1E+5), and any arithmetic goes through a double: jq '.id + 1' prints 12345678901234567000. The formatter below keeps every token as written, 1e5 included.

Gotchas

  • jq . data.json > data.json leaves an empty file: the shell truncates it before jq reads it. Write to a temporary file and mv it back.
  • A repeated key keeps its last value: {"a":1,"a":2} prints as {"a":2}.
  • jq reports the position where its reader stopped, which can be past the mistake. For {"name":"api","port":8080,} it reports Expected another key-value pair at line 1, column 27; the formatter below says Trailing comma before } at line 1, column 26, the comma itself.
  • jq -e . sets the exit status from the output, so a file that holds only null or false exits 1. Use jq empty to validate.

Try it in the JSON Formatter & Validator

Result
{
  "name": "café",
  "id": 12345678901234567890,
  "tags": [
    "api",
    "ops"
  ],
  "active": true,
  "manager": null
}

5 keys, nesting 2, 92 bytes in → 126 bytes out

Runs in your browser. Nothing you enter is sent anywhere.