The JSON rules that trip everyone up
Trailing commas, single quotes, comments, NaN. JSON looks like JavaScript and is much stricter, and the parser error rarely says so.
JSON was carved out of JavaScript object syntax, and it kept the appearance while dropping most of the flexibility. That resemblance is the whole problem: code that looks obviously fine to anyone who writes JavaScript is rejected outright, and the parser error usually points at a character rather than explaining the rule.
Trailing commas
This is the most common failure by a wide margin.
{
"name": "Ada",
"role": "Engineer", ← fine
} ← the comma above is notJavaScript has allowed trailing commas for years, and most formatters add them deliberately because they keep diffs clean. JSON forbids them entirely, in both objects and arrays. Worse, the error is reported at the closing brace — one line after the actual mistake.
} or ], look at the line above it. The problem is nearly always a comma with nothing following it.Quotes
JSON requires double quotes, for both keys and string values. Single quotes are not an alternative, and unquoted keys are not permitted at all:
{ name: "Ada" } ✗ key must be quoted
{ 'name': 'Ada' } ✗ single quotes
{ "name": "Ada" } ✓This bites hardest when copying an object literal out of source code, where all three forms are perfectly legal JavaScript.
Comments
There are none. No //, no /* */. Douglas Crockford removed them on purpose, having seen people put parsing directives in comments.
Config formats that appear to accept comments — tsconfig.json, VS Code settings — are using JSONC, a superset that specific tools understand. Send the same file to a strict parser and it fails. If you need a note inside real JSON, the usual workaround is a key nobody reads, like "_comment".
Numbers
JSON numbers are decimal only. All of these are invalid:
NaNandInfinity— not values JSON has0x1F— no hexadecimal.5— needs a leading zero1.— needs a digit after the point+5— a leading plus is not allowed
The subtler trap is precision. JSON does not specify a number size, but most parsers use a double, which stops being exact above 253. A 64-bit database ID travelling as a JSON number can arrive quietly rounded. The standard fix is to send large IDs as strings.
Only these types exist
String, number, boolean, null, object, array. That is the complete list. No dates, no undefined, no functions, no comments.
Dates get serialised as strings by convention — ISO 8601 like 2026-01-30T12:00:00Z, or a Unix epoch if you prefer a number. Both are conventions your code has to agree on, not something JSON enforces. If you are staring at an epoch and want to know what moment it refers to, our timestamp converter will tell you.
In JavaScript specifically, JSON.stringify silently drops object keys whose value is undefined. A field that vanished between sending and receiving was often never sent.
Duplicate keys
The specification does not forbid them, and it does not say what to do with them either. Most parsers keep the last one. Some keep the first. A few reject the document.
{ "id": 1, "id": 2 } → usually { "id": 2 }, but do not rely on itThis is worth knowing because it has been used as an attack: two systems parsing the same payload and disagreeing about which value counts.
Reading the error
Parser messages name a position, not a cause. Unexpected token at some offset means the parser reached a character that cannot follow what came before — the real mistake is usually just before it.
Our JSON formatter converts that offset into a line and column and names the likely cause, because “trailing comma at line 14” is a great deal more useful than “unexpected token at position 213”. It runs in your browser, so you can paste a production payload without it going anywhere.