A deliberately small format
JSON was designed to be the smallest data format that is still useful, and that smallness is the whole point: it is easy to write a parser, easy to read, and hard to disagree about. The grammar is defined identically by 8259 and (European Computer Manufacturers Association)-404, and it fits on a postcard. A JSON document is exactly one value, and a value is one of six things: an object, an array, a string, a number, a boolean, or null. Everything else is built from those.
The six value types
An object is an unordered set of members wrapped in curly braces, where each member is a string key, a colon, and a value: {"name": "Ada", "active": true}. An array is an ordered list of values in square brackets: [1, 2, 3]. A string is text in double quotes, with a fixed set of backslash escapes for special characters. A number is a decimal literal, which has subtleties worth its own article. A boolean is true or false, lowercase. And null is the literal null. Objects and arrays nest freely, and that nesting is what lets a flat grammar describe arbitrarily complex data.
The rules people forget
JSON is stricter than the JavaScript object literals it resembles, and the differences are where validation fails. Keys must be double-quoted strings: {name: 1} is invalid, and so is {'name': 1}, because single quotes are not allowed anywhere. There are no comments in JSON, despite how often people want them. There are no trailing commas, so [1, 2,] is an error. Numbers cannot have a leading zero or a leading plus, and they cannot be NaN or Infinity, because those are not representable in the grammar. A document must contain a single value and nothing after it, so two values in a row, or trailing text, is invalid.
Why a validator points to a location
Because the grammar is so rigid, every error has a precise location: the parser knows exactly which character violated which rule. A good validator reports not just that the document is invalid but where, by line and column, and which structural path it was reading at the time. That path, written as a JSON Pointer, turns a vague "syntax error" into "the value at /users/2/email is malformed," which is the difference between minutes and seconds of debugging. The formatter parses against this grammar and reports failures exactly that way.
This series, in order
This article opens the series JSON, exactly. The grammar above is the whole format; the parts below are the places where it meets real parsers, in the order a document meets them: its strings, its numbers, its keys, the tolerant dialects, its bytes when they are signed, and its translation into .
- JSON String Escapes and Unicode. The characters a string must escape,
\uXXXXfor any other, and the surrogate pair an emoji needs. - JSON Numbers and the Precision Trap. Why a number survives the grammar and not the parser: large integers and exact decimals lost to the 64-bit float.
- Duplicate Keys in JSON: Legal, Dangerous, and Worth Catching. Legal in the syntax, undefined in meaning: how parsers disagree about a repeated key, and why that can be a security bug.
- Trailing Commas, Comments, and the JSON5 Family. What JSONC and JSON5 allow that JSON does not, and how a tolerant editor produces a file a strict tool rejects.
- Formatting, Minifying, and Canonical JSON. Whitespace changes nothing until the bytes are signed or hashed; canonical JSON makes the same data the same string.
- JSON vs YAML: What Converts Cleanly and What Does Not. Every JSON document is YAML; what converts cleanly the other way, and what has no JSON equivalent. The bridge to the YAML series.