JSON that will not parse: the six things it almost always is
A parse error names a position, not a cause. Here are the six mistakes behind nearly every one, in the order they are worth checking.
The error tells you where, not what
Unexpected token } in JSON at position 247 means the parser was
fine until 247 and then met something it could not use. The mistake is usually
just before that position, not at it — a trailing comma at 245 is only
detected when the brace arrives at 247.
So read backwards from the position, not forwards. The JSON formatter reports the position and shows the surrounding text, which is generally enough to spot it immediately.
1. A trailing comma
By far the most common, because most programming languages allow it and JSON does not.
{ "a": 1, "b": 2, } ← invalid
{ "a": 1, "b": 2 } ← valid
Same rule in arrays. It bites hardest when you delete the last item of a list and leave the comma behind on the one above.
2. Single quotes
JSON strings use double quotes. Only double quotes. This is legal JavaScript and is not JSON:
{ 'name': 'Ada' } ← invalid
{ "name": "Ada" } ← valid
3. Unquoted keys
Every key is a quoted string, even one that looks like a plain identifier. JavaScript object literals do not require this; JSON does.
{ name: "Ada" } ← invalid
{ "name": "Ada" } ← valid
Together these three account for most failures, and all three have the same root cause: something pasted a JavaScript object literal where JSON was expected. They look nearly identical and they are not the same format.
4. NaN, Infinity and undefined
JSON has exactly one number type and no way to express those three. A language that serialises them anyway produces output nothing else will read.
{ "ratio": NaN } ← invalid
{ "ratio": null } ← valid
If you are generating JSON, decide what those values mean before serialising
— usually null, occasionally a string, never the bare word.
5. Comments
JSON has no comments. Not //, not /* */, not
#. This trips people up constantly in configuration files, because
several tools accept a superset called JSON5 or JSONC that does allow them, and
then a stricter parser downstream refuses the same file.
If you need a note, add a key for it: "_comment": "why this is 30".
Ugly, valid, and it survives every parser.
6. Characters a word processor inserted
The one that wastes the most time, because the file looks correct on screen. Paste JSON through a document editor, a chat client or a CMS field and you can get back:
- Smart quotes —
“and”instead of". Visually almost identical, completely different characters. - An en or em dash where a hyphen was typed.
- A non-breaking space instead of a space.
- A byte order mark at the very start of the file — invisible, and it makes the parser fail at position 0 on a document that looks perfect.
The text cleaner strips smart quotes, invisible characters and the BOM in one pass, which turns this from a half-hour of staring into a fix.
Two things that are legal and still cause trouble
Duplicate keys. {"a":1,"a":2} parses. The
specification does not say which wins, and implementations differ — most
take the last. If a value is mysteriously not what you set, check whether you set
it twice.
Large numbers. JSON numbers have no size limit, but most parsers read them as IEEE 754 doubles, which lose precision above 253. A 19-digit identifier will come back subtly wrong. Send those as strings.
A checking order
- Paste it into a formatter and read the reported position.
- Look at the few characters before that position.
- Search for
,]and,}— that is the trailing comma, found instantly. - Search for a single quote.
- If it still looks perfect, run it through the text cleaner. At that point it is almost always an invisible character.