JSON Formatting and Validation: Best Practices
July 22, 2026 · DevTools
An API returns a 40 KB blob on a single line, or a config file fails to parse and the only error is Unexpected token. Both problems have the same cure: a JSON formatter with real validation. This guide covers why JSON is so easy to break, the errors that cause most failures, and the formatting habits worth adopting.
You can follow along with the JSON Formatter — it validates, formats, and analyzes JSON entirely in your browser.
JSON is strict — stricter than JavaScript
JSON looks like a JS object literal, but the spec (RFC 8259) is far less forgiving:
| ❌ Invalid JSON | ✅ Valid JSON | Rule |
|---|---|---|
{ 'name': 'Ada' } | { "name": "Ada" } | Double quotes only |
{ name: "Ada" } | { "name": "Ada" } | Keys must be quoted |
[1, 2, 3,] | [1, 2, 3] | No trailing commas |
{ /* config */ } | { } | No comments |
{ "n": NaN } | { "n": null } | Only true, false, null, numbers |
That's why pasting a JavaScript object into a JSON parser fails. JSON5 and JSONC (JSON with Comments) exist precisely because people hate these rules — VS Code configs use JSONC — but APIs, package.json, and every standard parser enforce strict JSON. Know which dialect your file is before "fixing" it.
The errors that cause 90% of failures
When validation reports an error, it's usually one of these:
- Trailing comma —
{"a": 1,}— the classic, especially in hand-edited config - Unquoted key — from copy-pasting JS code
- Single quotes — same origin
- Smart quotes —
"value"copied from a document becomes"value"and breaks invisibly - Truncated paste — the blob got cut off mid-string; check the error's position
A good validator reports the line and character position of the first error, which turns a 10-minute hunt into a 10-second fix. The JSON Formatter pinpoints exactly where parsing failed.
Formatting conventions worth adopting
There's no single "right" style, but these habits pay off:
- 2-space indentation — the de facto standard (npm, most APIs); 4 spaces is fine, just be consistent within a project
- One key per line — makes
git diffshow exactly which key changed, instead of an entire line lighting up - Stable key order — tools like package managers sort keys so diffs stay minimal. Canonicalization (sorting keys recursively) also makes two documents comparable byte-for-byte — handy in tests
- UTF-8, no BOM — a byte-order mark before
{breaks strict parsers
{
"name": "devtools",
"version": "1.0.0",
"private": true
}
Minify for transport, format for humans
Formatting adds ~30–50% size in whitespace. The practical split:
- Format anything humans read: configs, fixtures, code reviews, documentation
- Minify anything machines move: API responses, JSON embedded in other JSON, storage where bytes matter
A formatter should do both directions in one click — paste minified JSON to read it, minify the pretty version before pasting it into a header or environment variable.
Validation beyond syntax: JSON Schema
A document can be syntactically perfect and still wrong — a missing email key, a string where a number belongs. JSON Schema lets you declare the expected shape (required keys, types, formats, ranges) and validate payloads against it. It's the standard behind OpenAPI specs and CI config validation, and it's the natural next step once "does it parse" is solved. Syntax validation catches typos; schema validation catches bugs.
Working with big documents
Beyond pretty-printing, real work on large JSON means:
- Validation first — is this even parseable?
- Search — find the one key in 5,000 lines
- Statistics — depth, key count, size; useful when debugging a payload that's grown out of control
The JSON Formatter combines all three with file upload and multiple format modes, so a 2 MB API dump is as manageable as a config snippet. On the command line, jq is the power tool for the same job (jq . file.json pretty-prints; jq '.users[0]' extracts).
Reading a validation error: a worked example
Error messages look cryptic until you parse them. Given:
{
"users": [
{ "name": "Ada", "admin": true, }
]
}
A parser says something like Unexpected token ] in JSON at position 52. Break it down: position 52 is the ] — the parser expected a value (because the trailing comma promised another key) but found the array's closing bracket. The position points at where the parser gave up, which is usually one token after the real mistake. When an error confuses you, look one step before the reported position.
JSON Lines: the format that isn't JSON
If you've ever been handed a .jsonl or "NDJSON" file that "won't parse", here's why: it's not one JSON document but one JSON object per line, a format designed for logs and streaming:
{"ts": "2026-07-22T10:00:01Z", "event": "login"}
{"ts": "2026-07-22T10:00:03Z", "event": "logout"}
Pasting the whole file into a JSON validator fails at line 2 — correctly. Parse it line by line (or wrap the lines into an array first), and each line will validate on its own.
Numbers: the precision trap
JSON's number type has no integer/decimal distinction, and most parsers map it to a 64-bit float. Two consequences:
- Integers above 2⁵³ (9,007,199,254,740,991) lose precision: Twitter snowflake IDs and database sequences routinely exceed this, which is why APIs serialize them as strings (
"id": "12345678901234567890"). If your formatter shows a long ID changing value, this is why. - Trailing zeros vanish —
1.50parses to1.5. For money, use integers of minor units (cents) or strings, never bare floats.
Formatting can't fix precision lost at parse time — if exact big integers matter, quote them at the source.
Formatting in editors and CI
Manual formatting doesn't scale across a team — automate it:
- Prettier handles JSON out of the box (
prettier --write .), and most editors format on save - CI check —
prettier --check .in a pipeline keeps committed JSON consistently formatted, so diffs stay meaningful jqfor ad-hoc shell work:jq . blob.jsonpretty-prints,jq -c .minifies,jq --sort-keys .canonicalizes
For one-off work — a response from a browser's network tab, a payload from a log — a browser-based formatter is faster than wiring up tooling, and that's the gap the JSON Formatter fills.
A security footnote
Two parser behaviors worth knowing:
- Duplicate keys —
{"a": 1, "a": 2}is legal JSON, and parsers disagree on the result (most take the last value). Proxy layers that parse twice have been exploited through exactly this. - Huge nesting depth — some parsers recurse and can be crashed with deeply nested input. If you parse untrusted JSON, set limits.
Common workflow
- Paste or drop the JSON into the formatter
- Fix validation errors starting at the reported position
- Format with 2-space indent to read or review
- Minify before embedding anywhere space-sensitive
- Need YAML or CSV instead? Convert with the JSON to YAML Converter or the CSV to JSON Converter
Everything stays in your browser
JSON payloads routinely contain tokens, user data, and internal URLs. The formatter runs 100% client-side — paste production API responses without a second thought.
Next steps
- Validate a payload now: JSON Formatter
- Working with TypeScript? Generate types from your JSON with the JSON to TypeScript tool
- Comparing formats for a new config file? Read JSON vs YAML vs CSV vs TOML