What formatting actually does
Formatting JSON — equivalently: beautifying, prettifying, or pretty-printing it — means adding newlines and indentation so the structure of the document becomes visible to a human reader.
The reason this is safe is that whitespace between tokens is insignificant in JSON. RFC 8259 permits space, tab, newline, and carriage return between any two structural tokens. These two documents are byte-different and semantically identical:
{"id":42,"roles":["admin","engineer"],"active":true}
{
"id": 42,
"roles": [
"admin",
"engineer"
],
"active": true
}
A formatter parses the input into a value, then re-serialises that value with indentation. Because parsing comes first, formatting is also validation — if the document is malformed there is nothing to re-serialise, and you get an error instead of output. That is why a formatter is the fastest way to find out whether JSON is well-formed.
What formatting does not preserve
Two details surprise people, and both follow from formatting being a parse-then-print operation rather than a text transformation.
Numbers are normalised. The parser converts each number to a double-precision float, and the serialiser prints the shortest representation that round-trips. So 1.50 comes back as 1.5, 1e3 as 1000, and 1.0 as 1. The value is unchanged; the spelling is not.
Key order is preserved but meaningless. Most parsers keep insertion order, so formatted output usually matches input order. Nothing in the specification requires this, so do not build anything that depends on it.
Formatting never changes string contents, boolean values, null, or the structure itself.
2 spaces or 4?
JSON has no preferred indentation. Convention differs by ecosystem, and following the local one avoids pointless diffs:
| Width | Used by | Notes |
|---|---|---|
| 2 spaces | JavaScript, TypeScript, Node | What npm writes into package.json; Prettier's default |
| 4 spaces | Python, .NET, Java | Matches json.dumps(indent=4); easier to scan when deeply nested |
| Tabs | Rare | Permitted, but width varies between viewers, so shared files render inconsistently |
Deep nesting is the practical argument for 2 spaces: at six levels, 4-space indentation has pushed content 24 columns right before any content appears. The argument for 4 is legibility at shallow depth on a wide screen.
The decision that actually matters is consistency within a repository. Mixed indentation produces diffs where nothing meaningful changed, which wastes review time. If your project runs Prettier or has an .editorconfig, let that own the choice.
Formatting in code
Every major language exposes the same parse-then-print operation.
// JavaScript / Node.js — the third argument is the indent width
const formatted = JSON.stringify(JSON.parse(raw), null, 2);
// A string third argument is used literally, so tabs work too
const tabbed = JSON.stringify(value, null, "\t");
# Python
import json
formatted = json.dumps(json.loads(raw), indent=2)
# sort_keys gives a stable diff regardless of input order
stable = json.dumps(obj, indent=2, sort_keys=True)
# Command line — jq formats by default
jq . response.json
curl -s https://api.example.com/users | jq .
# Python's stdlib, no dependency required
python -m json.tool response.json
Two gotchas worth knowing. In JavaScript, JSON.stringify silently drops undefined values, functions, and symbols from objects, and converts them to null inside arrays — so a round-trip is not always lossless. In Python, json.dumps inserts a space after each separator by default; pass separators=(",", ":") when you want a genuinely minimal document.
Formatting in editors
- VS Code —
Shift+Alt+F(Windows/Linux) orShift+Option+F(macOS). Built in; no extension needed. Width followseditor.tabSize. - JetBrains IDEs —
Ctrl+Alt+L/Cmd+Option+L. - Sublime Text — requires a package such as Pretty JSON.
- Vim —
:%!jq .pipes the buffer throughjq.
For a one-off paste from an API response or a log line, a browser-based formatter is usually faster than any of these, because there is no file to create and no tool to configure.
When formatting fails
If the formatter returns an error instead of output, the document is not valid JSON. The error text names the symptom; the cause is almost always one of a small set of JSON-vs-JavaScript differences — a trailing comma, single quotes, an unquoted key, or an invisible byte order mark.
Common JSON Errors covers each one with its fix, and JSON Syntax Rules explains the rules they violate.