Formatting · September 3, 2026

JSON formatting best practices — indentation, readability, and the debates that won't die

Tabs vs spaces, trailing commas, sorted keys, compact vs pretty — every JSON formatting decision has a trade-off. Here's what actually matters.

JSON’s grammar is minimal. Six value types, no comments, no trailing commas, no flexibility in how strings are quoted. That strictness is its strength for machines and its weakness for humans. When a human has to read or write JSON — in a config file, an API response, a diff — formatting matters.

This post covers every formatting decision you’ll face, what the ecosystem settled on, and where the debates still rage.

Indentation: 2 spaces is the winner

The Tabs vs Spaces war has a winner in JSON land: 2 spaces. Nearly every major style guide, linter, and formatter defaults to 2-space indentation:

  • Google JSON Style Guide — 2 spaces
  • Prettier — 2 spaces (default)
  • ESLint — 2 spaces (most configs)
  • AWS CloudFormation — 2 spaces
  • Kubernetes manifests — 2 spaces

The reason is practical: JSON is already verbose with its quotes and braces. 4-space indentation pushes nested objects off the right edge of most editors. 2 spaces keeps things readable without wasting horizontal space.

Use 4 spaces if your team prefers it and you’re consistent. Use tabs if you must, but be aware that most JSON tooling assumes spaces, and mixed indentation in a JSON file is a parse error waiting to happen.

Trailing commas: still no

JSON does not allow trailing commas. This is the single most common syntax error in hand-edited JSON files. You write:

{
  "name": "Alice",
  "items": ["a", "b",],
}

And a strict parser rejects it. The trailing comma after "b" and the trailing comma after the closing } are both illegal.

YAML allows trailing commas (and most languages do). JSON doesn’t. If your tooling supports JSONC (JSON with Comments, used in VS Code’s tsconfig.json and settings.json), trailing commas are allowed. But plain JSON — the kind that travels over APIs — does not tolerate them.

The best defense: use a formatter that catches this automatically. Paste your JSON into a validator before committing.

Pretty vs compact

Pretty-printed JSON has newlines and indentation. It’s readable, diffable, and debuggable:

{
  "status": "ok",
  "count": 42
}

Compact JSON has no whitespace between tokens. It’s smaller on the wire:

{"status":"ok","count":42}

The rule of thumb:

  • Human-facing (config files, logs, API responses during debugging) → pretty-print.
  • Machine-facing (production API payloads, message queues, event streams) → compact.
  • Storage (databases, caches) → compact, unless you need to read it manually during debugging.

Compact JSON saves roughly 20-30% in size compared to 2-space pretty-printed JSON. For a 10KB payload, that’s 2-3KB. Over millions of requests, it adds up. For a config file you edit by hand, the readability of pretty-printed JSON is worth the extra bytes.

Sorted keys

Should object keys be sorted alphabetically?

In favor: diffs are deterministic. If you add a key, only that line shows up in a git diff. Without sorted keys, inserting a key in the middle can shift every subsequent key, creating a noisy diff.

Against: logical grouping is more readable. Putting "name" first and "id" second is intuitive. Alphabetical sorting puts "address" before "name" for no semantic reason.

The pragmatic answer: sort keys in machine-generated JSON (APIs, configs, diffs). Keep logical order in hand-written JSON. Most formatters (Prettier, jq, python -m json.tool) have a --sort-keys flag you can enable in CI.

Key naming conventions

JSON keys are strings, and the ecosystem has settled on two conventions:

  • camelCase — the JavaScript/Node.js default. firstName, lastName, createdAt.
  • snake_case — the Python/Ruby/Rust default. first_name, last_name, created_at.
  • kebab-case — rare in JSON, more common in URLs and CSS. Avoid for API keys.

Pick one and stick with it. Most APIs use camelCase. If you’re building a REST API for JavaScript consumers, camelCase is the path of least resistance. If you’re interfacing with Python services, snake_case reduces friction.

The worst thing you can do is mix them: firstName in one endpoint, last_name in another. Pick a convention, enforce it with a linter, and move on.

Number formatting

JSON doesn’t distinguish integers from floats. 42 and 42.0 are both valid, and most parsers treat them identically. But formatting matters for readability:

  • Integers: no decimal point. 42, not 42.0.
  • Floats: use as many digits as you need. 3.14159, not 3.14159000000000.
  • Large numbers: use scientific notation if the number is huge. 1e10 is clearer than 10000000000.

JSON does not support Infinity, -Infinity, or NaN. If your language serializes these, the output is not valid JSON and parsers will reject it.

Strings: single vs double quotes

JSON requires double quotes for strings. This is not negotiable. 'hello' is not valid JSON. "hello" is.

If your linter or editor allows single quotes in JSON files, it’s parsing JSONC or a superset, not standard JSON. APIs and parsers that expect strict JSON will reject single-quoted strings.

Comments: still not allowed

JSON has no comment syntax. This is by design (the spec says JSON is “a data interchange format,” not a configuration language), but it’s the most common complaint from developers who use YAML.

Workarounds:

  • Use a "comment" or "_comment" key. It’s ugly but valid.
  • Use JSONC (VS Code’s format) if your tooling supports it.
  • Switch to YAML or TOML for config files where comments matter. See our YAML vs JSON comparison for more details.

The formatter workflow

The best workflow for JSON formatting:

  1. Write JSON however you want. Don’t waste time indenting by hand.
  2. Run a formatter on save. Prettier, jq, or your editor’s built-in formatter.
  3. Commit the formatted output. Consistent diffs, no style debates.
  4. Validate in CI. A JSON lint step catches trailing commas and syntax errors before they reach production.

This eliminates every formatting debate. The formatter decides, everyone else writes code.

Common mistakes

  • Trailing commas — the most frequent parse error in hand-edited JSON.
  • Single quotes — valid in JavaScript object literals, invalid in JSON.
  • Unquoted keys — { name: "Alice" } is JavaScript, not JSON.
  • Comments — // this is not JSON or /* this either */.
  • Mixed indentation — mixing tabs and spaces in the same file.

Paste your JSON into a validator before deploying. It takes one second and saves thirty minutes of debugging a mysterious 400 error.