JSON is everywhere — API responses, config files, log lines, message queues. Most of the time it comes to you minified: one long line with no whitespace, perfect for a machine, useless for a human trying to figure out why the third nested object is null. Formatting JSON is the act of adding consistent indentation and line breaks so you can actually read it.

Sounds trivial. It mostly is. But there are enough sharp edges that it's worth being deliberate about it.

What formatting JSON actually does

A JSON formatter (also called a beautifier or pretty-printer) parses the document into an in-memory structure, then re-serialises it with whitespace rules applied. Two things matter here:

  • It validates as it parses. If the JSON is malformed, a good formatter tells you where it broke instead of silently mangling it.
  • It's a round-trip on the data, not the text. The output represents the same object, but key order, number formatting, and whitespace may change.

That second point catches people out, so keep it in mind.

When you'd reach for it

A few situations come up constantly:

  • Debugging API responses. You copy a payload from the network tab, it's a 4KB single line, and you need to find one field. Format it and the structure becomes obvious.
  • Reviewing config files. A minified tsconfig or CI config in a diff is unreadable. Formatted, the change stands out.
  • Writing fixtures and test data. Human-editable JSON should be indented so future-you can maintain it.
  • Reading logs. Structured logs are often single-line JSON per entry. Pulling one out and formatting it saves your eyes.

For quick one-offs, I keep a browser tab on a JSON Beautifier — paste, format, done. No installing anything, no worrying about a CLI flag. For anything that lives in the repo, formatting belongs in your editor or a pre-commit hook.

The gotchas

Indentation isn't standardised

Two spaces? Four? Tabs? JSON itself doesn't care — the spec allows any whitespace between tokens. Pick a convention per project and enforce it, otherwise you get noisy diffs where someone's editor reformatted with four spaces and yours uses two. Tools like Prettier default to two spaces for JSON, which is a sensible baseline.

Key order can change — and it shouldn't matter

Some formatters sort keys alphabetically, others preserve insertion order. JSON object keys are unordered by definition, so no consumer should depend on order. But if you sort keys before committing and your teammate doesn't, you'll get a giant diff. Agree on one behaviour.

JSON is not JavaScript

This trips up beginners often. JSON does not allow:

  • Trailing commas ([1, 2, 3,] is invalid)
  • Comments (// like this)
  • Single-quoted strings
  • Unquoted keys

If you paste a JavaScript object literal into a JSON formatter and it complains, that's usually why. Formats like JSON5 and JSONC relax these rules, but plain JSON is strict.

Numbers and precision

Large integers can lose precision when parsed into a floating-point number and re-serialised. If your JSON contains something like an ID 9007199254740993, a naive round-trip through a formatter may turn it into 9007199254740992. When precision matters, IDs should travel as strings. Don't blame the formatter — blame the schema.

Encoding and BOMs

A byte-order mark or non-UTF-8 encoding at the start of a file will make some parsers reject the document with a cryptic error. If a file that looks fine won't parse, check for invisible characters at the top.

A short worked example

Here's a typical minified response you might grab from a log:

{"id":42,"name":"Ada","roles":["admin","editor"],"active":true,"meta":{"lastLogin":"2024-01-15T09:30:00Z","loginCount":128}}

Unreadable in a hurry. Formatted with two-space indentation, it becomes:

{
  "id": 42,
  "name": "Ada",
  "roles": [
    "admin",
    "editor"
  ],
  "active": true,
  "meta": {
    "lastLogin": "2024-01-15T09:30:00Z",
    "loginCount": 128
  }
}

Now the nesting is obvious. You can see at a glance that meta is an object with two fields, and roles is an array of strings.

If you want to do this in code, every major language ships a formatter. In JavaScript:

const obj = JSON.parse(raw);
const pretty = JSON.stringify(obj, null, 2);
console.log(pretty);

The third argument to JSON.stringify is the indent — pass 2 for two spaces, or "\t" for tabs. In Python it's just as short:

import json
print(json.dumps(obj, indent=2))

And from the command line, jq pretty-prints by default:

echo '{"a":1}' | jq .

Minify when you ship, format when you read

The flip side of beautifying is minifying — stripping all optional whitespace. That matters for anything sent over the wire or stored at scale, where every byte counts. The rule of thumb I follow:

  • Minified for transport and storage. Smaller payloads, faster parsing.
  • Formatted for humans — config files in the repo, fixtures, anything you'll read or edit.

Never hand-maintain minified JSON. And never ship formatted JSON as an API response just because it looks nice; that's wasted bandwidth on every request.

Make it automatic

The best formatting workflow is one you never think about. Set up your editor to format JSON on save, add a Prettier or equivalent step to your pre-commit hook, and let CI reject unformatted files. That keeps diffs clean and stops the two-spaces-versus-four bikeshedding from ever happening.

For the ad-hoc case — a payload you pasted from somewhere, a log line you're chasing — a quick online formatter that also validates is the fastest path. Paste, spot the error, move on. That combination of readability plus instant validation is why formatting JSON stays a daily habit rather than a rare chore.

Photo by Chris Ried on Unsplash