Developer FIELD NOTES · 5 MIN READ
JSON Explained: The Format the Web Runs On
Six JSON value types, the strict syntax rules, pretty vs minified, the big-number precision trap, and why JSON is not JavaScript.
JSON — JavaScript Object Notation — is the language machines use to talk to each other: every REST API response, most modern config files, webhooks, log lines, and JWT payloads are JSON under the hood. The entire specification fits on roughly one page, and that smallness is exactly why it won: six kinds of values, a couple of delimiters, and almost no room for disagreement between parsers.
The whole grammar: six kinds of value
Every JSON document is a single value, and that value can only be one of six things: an object, an array, a string, a number, true/false, or null. Objects map string keys to values; arrays hold ordered values; everything else is a leaf. Nest the containers and you can express almost any data:
{
"id": 7241,
"name": "Ada Lovelace",
"verified": true,
"tags": ["math", "computing"],
"address": { "city": "London", "postcode": null }
}
That one object uses all six kinds: a number, a string, a boolean, an array of strings, and a nested object containing null. It is worth separating null from its neighbours — it means "deliberately empty", which is different from an empty string "" (a value that happens to be blank), from 0 (a number), and from a missing key, which some languages surface as undefined. JSON has no undefined; if a key is absent, you find out by looking.
The strict rules that trip people up
JSON is forgiving about whitespace and merciless about punctuation. Four rules produce most real-world parse errors:
{ "name": 'Ada' } ← single quotes: invalid
{ name: "Ada" } ← unquoted key: invalid
{ "a": 1, "b": 2, } ← trailing comma: invalid
{ "n": /* hi */ 1 } ← comments: invalid
Keys must be double-quoted strings, string values must use double quotes, there are no trailing commas, and there is no comment syntax at all. That last one is a deliberate design decision — it keeps parsers tiny and files unambiguous — but it is also the single biggest reason hand-edited configuration moved to formats like YAML and TOML, which allow comments (compared in YAML vs TOML vs JSON).
Pretty vs minified: same data, two outfits
Whitespace between tokens is not part of the data. A parser skips spaces, tabs, and newlines outside strings, so this:
{"a":1,"b":[2,3]}
…means exactly the same as the spread-out version with one key per line. Pretty-printing (indentation, consistent spacing) is for humans reading, reviewing, and diffing files; minification — stripping every non-essential byte — is for transport and storage. A typical pretty-printed API response shrinks 70–80% when minified, which is why servers minify by default and developer tools pretty-print on demand. One exception matters: whitespace inside strings is data. "a b" keeps its double space no matter how you format the surrounding file.
Numbers, and the precision trap
The number grammar is minimal: optional minus, digits, optional fraction, optional exponent — no hex, no leading zeros, no NaN or Infinity. The trap is precision. The spec does not define how exact numbers must be, and every mainstream parser reads them into IEEE 754 double-precision floats, which represent integers exactly only up to 253 − 1 = 9,007,199,254,740,991. One above that:
9007199254740993 // what you wrote
9007199254740992 // what JavaScript parses and prints
The final digit silently vanishes. This is why APIs that issue very large numeric IDs — Twitter snowflakes, Discord IDs — deliver them as strings: "id": "175928847109932151". Quoting the ID costs nothing and guarantees it survives every JavaScript client intact. If you design an API and your IDs exceed 253, quote them.
JSON is not JavaScript — and not a regex problem
The name misleads. JSON borrowed JavaScript's literal syntax as a data format, but it is not executable JavaScript: {name: "Ada"} is a valid JS object literal yet invalid JSON (unquoted key); {'name': 'Ada'} is valid JS and invalid JSON; functions, undefined, and trailing commas exist in JS but not in JSON. Parse with JSON.parse, never eval — eval executes whatever it is handed, and JSON arriving over a network is untrusted input.
It is also not something you can match with string patterns. JSON nests — braces inside arrays inside braces — and matching nested structure is exactly what regular expressions cannot do reliably (they match flat text; see How Regular Expressions Work). The robust pipeline is always: parse first, then query the resulting structure. A regex that "works" on your test payload will meet a string containing "}"," one day and lose.
Where it shows up — and how it breaks in the wild
Beyond APIs, JSON appears in webhooks, structured log lines, JSON-LD metadata embedded in web pages, and inside JWTs, where the header and payload are Base64-encoded JSON strings (see How Base64 Encoding Works for that layer). The failures that actually fill validators' logs are mundane: "smart quotes" pasted from a word processor (“curly” instead of "straight"), a UTF-8 byte-order mark sitting invisibly before the first {, a literal line break inside a string (it must be written as the escape \n), and undefined sneaking into output built by string concatenation. A validator that reports the exact line and character of the first problem turns minutes of staring into seconds.
Try it yourself
Paste any document into the JSON Validator — it parses and reports the first error with its position, so "what's wrong here?" stops being a guessing game. Run clean documents through the JSON Formatter to pretty-print them at your preferred indentation, and through JSON Minify to strip the whitespace and see how many bytes a payload really needs on the wire.