Skip to main content
Workflow · 6 min read

How to Format JSON (and When Not To)

Formatting, minifying and canonicalising JSON: what each does, which indentation to choose, and why you should not minify files that live in version control.

Formatting JSON — pretty-printing, beautifying, whatever you call it — is a round trip: parse the document into memory, then serialize it again with indentation. The data that comes out is identical to the data that went in. Only the bytes a parser ignores change.

That makes it a safe operation, and it makes the interesting questions the ones about workflow rather than about correctness.

Formatting in the browser

Paste into the JSON formatter, pick an indentation, press Format. Everything runs locally, so it works on data you are not allowed to paste into a random web service.

Formatting from the command line

# jq — the standard tool, formats by default
jq . input.json > output.json

# Python, no extra install
python3 -m json.tool input.json output.json

# Node
node -e "const fs=require('fs');console.log(JSON.stringify(JSON.parse(fs.readFileSync(0,'utf8')),null,2))" < input.json

All three parse and re-serialize, so all three will fail loudly on invalid input. That is a feature: a formatter is a cheap syntax check.

Which indentation?

  • Two spaces — the default almost everywhere. npm, jq and most editors emit it. Choose this unless you have a reason not to.
  • Four spaces — easier to scan in shallow configuration files, wasteful in deeply nested documents.
  • Tabs — the accessible choice, since tab width is a reader preference rather than a file property. Uncommon in JSON.

The real rule: match the file. A formatter that rewrites every line of a file in a pull request buries the one line that actually changed.

Sorting keys

Sorting object keys alphabetically produces a canonical form. Two documents with the same data then produce the same text, which makes them comparable by eye, by diff, or by checksum.

It is the wrong default for hand-edited files, where the author put the important keys first on purpose. Turn it on when you are normalising machine output, leave it off for configuration.

Minifying: the other direction

The minifier strips every optional space and newline. Typical savings are 10–40% of the raw byte count, depending on nesting depth and how short your keys are.

Before you reach for it, check whether it will actually help. Almost every server applies gzip or brotli, and both compress repeated whitespace to nearly nothing. On a compressed transfer, minifying often saves a couple of percent rather than a third.

Where it does clearly help: payloads with a hard size limit — cookies, query strings, message queue messages, log lines — and JSON embedded in HTML, which is frequently not compressed separately.

When not to format

  • Never reformat a file you are also changing. Do the formatting in its own commit so reviewers can see the real change.
  • Never minify a file in version control. A single-line file produces a single-line diff for every change, which makes review impossible.
  • Do not reformat a fixture used in a byte-for-byte test. The test is asserting on the exact text.
  • Do not add a whitespace-only change to a file with an active pull request against it. You will create a conflict for someone.

Automate it

For a repository, put formatting in a pre-commit hook or in CI so it happens the same way for everyone. Prettier handles .json out of the box; jq --indent 2 works in a shell hook. The point of automating it is not the formatting itself — it is that nobody has to think about it again.

When a file will not format, it will not parse. The validator will tell you the line, the column and what specifically is wrong.