Core answer: JSON has exactly six types: string, number, boolean, null, object, array. Strict rules: double quotes only, no trailing commas, no comments, no undefined, no functions. Most parse errors come from five causes — single quotes, trailing commas, unquoted keys, comments, and literal Infinity/NaN. Format with 2-space indent for humans; minify for transport.
The grammar in 60 seconds
{"string": "double quotes only", "number": 42, "float": 3.14, "bool": true, "nothing": null, "object": {"nested": "yes"}, "array": [1, "two", false]}
That's the entire language. Keys are always strings. No dates, no undefined, no regexes, no functions — serialize those as strings/numbers yourself.
The five parse killers
| Error | Bad | Fixed |
|---|---|---|
| Single quotes | {'a': 1} | {"a": 1} |
| Trailing comma | {"a": 1,} | {"a": 1} |
| Unquoted key | {a: 1} | {"a": 1} |
| Comment | {"a": 1 /* x */} | remove it |
| NaN/Infinity | {"v": NaN} | {"v": null} |
Worked examples
Example 1 — API debugging. A 400 error on POST: the body had "price": 19.90, (trailing comma before }). Python's json module says "Expecting property name enclosed in double quotes: line 3 column 5" — the line:column is your flashlight.
Example 2 — Config files. package.json forbids comments, which is why JSONC (VS Code settings) and JSON5 exist — but they're NOT JSON; a strict parser will reject them. Keep build configs in strict JSON, human-edited settings in JSONC.
Example 3 — Big-integers hazard. {"orderId": 9007199254740993} parses in JS as 9007199254740992 — beyond Number.MAX_SAFE_INTEGER (2⁵³−1). IDs larger than that must be strings: {"orderId": "9007199254740993"}.
Example 4 — Streaming large files. A 2 GB JSON array won't fit in memory; use NDJSON (one object per line) and process line-by-line — that's why logs and LLM streams use it.
Common mistakes and myths
- JSON.stringify for deep clones — it drops undefined, functions, and converts Dates to strings; use structuredClone() in modern runtimes.
- Trusting parse without try/catch — user-uploaded JSON will be malformed; always handle SyntaxError gracefully.
- Assuming key order is guaranteed — JS preserves insertion order practically, but the spec doesn't promise it; never encode meaning in key order.
- Pretty-printing in production APIs — whitespace is 10–30% of payload; minify transport, pretty-print only for humans.
- Storing "null" as string — "null" ≠ null; validate types at the boundary (zod, pydantic) before they infect your logic.