Developer

The JSON errors everyone hits, and what the spec actually says

JSON is a deliberately tiny format. Most parse errors come from writing JavaScript object syntax and expecting a JSON parser to accept it.

3 minute read

JSON's whole design goal was to be small enough to specify on a business card. That minimalism is why it won, and also why people constantly write things it does not allow, because those things are legal in JavaScript, which JSON only superficially resembles.

The five that account for most failures

1. Trailing commas.

{ "a": 1, "b": 2, }

Legal in modern JavaScript, illegal in JSON. The error message usually points at the closing brace, one position after the actual problem, which is why people stare at the wrong line.

2. Single quotes. JSON strings must use double quotes. {'name': 'value'} is a JavaScript object literal, not JSON.

3. Unquoted keys. {name: "value"} is likewise JavaScript. Every key in JSON is a double-quoted string.

4. Comments. There is no comment syntax in JSON. Not //, not /* */, not #. If you need commented configuration, use YAML, TOML, or JSON5, but know that you are no longer writing JSON.

5. Unescaped characters inside strings. Literal newlines, tabs and unescaped double quotes inside a string value all break parsing. They must be written as \n, \t and \". This one shows up constantly when someone pastes multi-line text into a JSON field by hand.

Also not allowed: NaN, Infinity, undefined, hexadecimal numbers, leading + on numbers, and leading zeros like 012.

The number problem nobody warns you about

JSON numbers have no defined precision limit. JavaScript's Number is a 64-bit float, which can represent integers exactly only up to 2⁵³−1 (9,007,199,254,740,991).

So this happens:

JSON.parse('{"id": 9007199254740993}').id
// → 9007199254740992

The value changed silently. No error, no warning.

This bites hard with large database IDs, Twitter/X-style snowflake IDs, and financial values in the smallest currency unit. The standard fix is for the API to send those values as strings. If you control the parser, JSON.parse accepts a reviver function, and BigInt can hold the value once you have it as a string.

Related: never store money as a JSON float. 0.1 + 0.2 is not 0.3 in binary floating point, and rounding errors in currency have a way of becoming someone's problem later.

Duplicate keys are undefined behaviour

{"a": 1, "a": 2} is not an error by the letter of the spec, and different parsers do different things, most take the last occurrence, some take the first, some raise. Never rely on it.

Reading a parse error efficiently

Parse errors report the position where the parser gave up, which is usually after the mistake. A missing comma between two objects is reported at the start of the second object; a missing closing brace is reported at the end of the file.

The fastest way to locate a structural error in a large document is to format it. Pretty-printing with consistent indentation makes an unbalanced bracket visible immediately, because the indentation stops lining up. Collapsing sections narrows it down further.

A short checklist

  1. Format the document to see its structure.
  2. Check the ending: unbalanced braces or brackets are the most common structural fault.
  3. Search for ', single quotes should not appear outside string content.
  4. Search for ,] and ,} to find trailing commas.
  5. Look for large integers that might be silently truncated.
  6. Confirm the file is UTF-8 without a byte order mark, a BOM before the opening brace fails many parsers.

JSON vs the alternatives

JSON5 / JSONC allow comments, trailing commas and unquoted keys. Fine for config files you control; not something to send over an API.

YAML is far more readable for configuration and far more dangerous, significant whitespace, and the classic surprise where an unquoted no becomes boolean false and 3.10 becomes the number 3.1.

NDJSON (one JSON object per line) is the right choice for logs and streams, because a broken line does not invalidate the whole file.

When a parser rejects a document, paste it into a JSON formatter. It shows the parser's own error message, which in current browsers includes the line and column of the first problem, and that is almost always one of the mistakes above.

Further reading

Do it hereJSON FormatterFormat, minify, validate, repair and explore JSON with tree inspectorOpen

Written for NextTool. Every statement about a tool is checked against that tool's code, and corrections are dated above. How guides are written

jsonparsingapi