JSON Validation & Formatting: The Anatomy of Structured Data

JSON is the lingua franca of modern software: APIs speak it, configuration files are written in it, logs are shipped in it, and entire NoSQL databases store documents natively in it. Yet it is astonishingly easy to break — a single stray comma silences an integration, and a “smart quote” pasted from a word processor produces an afternoon of debugging. This guide dissects the format precisely, so you can read parser errors like sentences instead of runes.

The entire grammar, in six rules

JSON is defined by RFC 8259, and the grammar is small enough to hold in your head:

  1. A value is exactly one of: an object, an array, a string, a number, true, false, or null. Nothing else exists.
  2. An object is an unordered set of "key": value pairs inside { }. Keys are always strings — unquoted JavaScript-style keys are invalid.
  3. An array is an ordered list of values inside [ ], comma-separated, with no trailing comma.
  4. A string is double-quoted Unicode with a fixed escape table (\", \\, \/, \b, \f, \n, \r, \t, \uXXXX). Single quotes and literal control characters are forbidden.
  5. A number is decimal with an optional exponent. NaN, Infinity, hexadecimal and leading zeros are all invalid.
  6. Whitespace (spaces, tabs, newlines) may appear between tokens — but never inside them. There are no comments.

Where validation actually fails

Real-world breakage clusters into a handful of recurring patterns. Recognising them by sight turns hours of hunting into seconds:

Broken inputWhy it failsTypical parser message
{"a": 1,}Trailing comma before a closing braceUnexpected token }
{a: 1}Key not quoted (valid JS, invalid JSON)Unexpected token a
{'a': 1}Single-quoted stringUnexpected token '
[1, NaN]NaN/Infinity are not JSON numbersUnexpected token N
{"a": "x–y"} with “smart quotes”Typographic quotes from word processors are not ASCII "Unexpected token in JSON
File starts with {UTF-8 BOM before the first tokenUnexpected token ï
{"a": 01}Leading zero (Octal-looking literal)Unexpected number

Good validators go beyond “invalid” and report the exact line and column plus a human paraphrase — because position 4172 alone helps nobody.

Formatting vs minifying — and what re-serialisation really does

Both operations are the same two-step dance: parse the text into an in-memory tree, then emit it again with your chosen whitespace policy (2-space, 4-space, tab, or minified). But re-serialisation has side effects worth knowing:

  • Key order is preserved as encountered in most engines — but keys that look like non-negative integers ("3", "42") get hoisted to the front of objects in JavaScript. Round-tripping can silently reorder them.
  • Numbers may not survive verbatim. 1.50 comes back as 1.5; very large integers lose precision beyond 2⁵³ (see below); 1e999 parses to Infinity and then serialises as null.
  • Escapes are normalised. \u0041 becomes A; literal newlines inside strings remain illegal either way.
  • Duplicate keys collapse. Most parsers keep the last occurrence and discard the rest — a data-loss bug masquerading as tidiness.
Precision warning: JavaScript numbers are IEEE 754 doubles, so identifiers like 9007199254740993 silently round to ...992. If your payloads carry 64-bit IDs, a serious validator should flag them — and you should parse them as strings or BigInt.

JSON Schema in sixty seconds

Syntax validation proves the document parses. Schema validation proves it means something. A JSON Schema describes the shape your data must have:

{
  "type": "object",
  "required": ["id", "email"],
  "properties": {
    "id":    { "type": "integer", "minimum": 1 },
    "email": { "type": "string", "format": "email" },
    "role":  { "type": "string", "enum": ["admin", "member", "guest"] }
  },
  "additionalProperties": false
}

Against this schema, a syntactically perfect {"id": "abc"} still fails — the type is wrong. Schemas catch the class of bugs that unit tests usually discover in production: renamed fields, optional values that stopped being optional, enums that grew a new spelling.

Why validation belongs in your browser

Here is the uncomfortable part: JSON payloads are rarely innocuous. They contain API tokens, session cookies, customer records, internal hostnames, personal data. Paste such a payload into a random “free JSON formatter” website and you have transmitted confidential material to an unknown operator over an unencrypted-on-trust channel — many of those sites explicitly log inputs.

Validation is, mechanically, a pure function: bytes in, tree plus errors out. It needs no network, no GPU, no server of any kind. That is why json.clicktools.app parses, formats and schema-checks entirely in your tab — the same RFC 8259 grammar, executed locally, with zero possibility of your payload appearing in someone else's logs.

The takeaway

JSON's strength is its smallness: six grammar rules cover every document ever written. Learn the failure patterns, treat re-serialisation as a transformation (not a no-op), graduate from syntax checking to schemas as soon as money or identity touches the payload — and prefer validators that never see your data leave the building.

Next in the series: why 0.1 + 0.2 ≠ 0.3 — and what that means for unit converters.

Unit conversion precision →