Home › Guides › Trailing commas, single quotes and unquoted keys — the "almost JSON" family
Trailing commas, single quotes and unquoted keys — the "almost JSON" family
Direct answer: these are JavaScript/Python habits in JSON clothing. JSON requires double-quoted strings and keys, and forbids trailing commas and comments outright. The good news: this whole family is deterministic to convert — quote the keys, convert the strings, drop the trailing commas — and the tool below does it while listing every single change.
Convert almost-JSON to JSON — with the changes listed
Processed in your browser, so big pastes don't freeze the page. Nothing is uploaded — check your browser's network tab if you'd like to verify.
The family, member by member
| Construct | Where it comes from | JSON verdict | Safe mechanical fix? |
|---|---|---|---|
Trailing comma [1, 2,] | Modern JS, Python, hand edits | Illegal | Yes — remove it; it carries no data |
Single-quoted strings 'name' | JS literals, Python dicts, LLMs imitating both | Illegal | Yes — convert quotes, normalise escapes |
Unquoted keys {name: 1} | JS object literals | Illegal | Yes — quote the key |
Comments // note | JSONC configs, hand annotation | Illegal | Yes — remove; they are not data |
Missing comma [1 2] | Hand edits, generator bugs | Illegal | Yes — the boundary is unambiguous between two values |
True / None / undefined / NaN | Python / JavaScript values | Illegal | Yes — map to true / null, and note it in the report (a string "None" and a null are different data) |
Missing value {"a": } | Template bugs | Illegal | No. Any fill-in is invented data — this tool fails honestly instead |
Why "almost JSON" keeps appearing
Because the producers are not JSON encoders. Someone writes a JavaScript object and copies it out of the console; a Python developer prints a dict with print() instead of json.dumps(); a template interpolates values into a JSON-shaped string; an LLM imitates all three. Each produces text that looks like JSON to a human and is not JSON to a parser. The fix at the source is always the same advice: use the language's real serialiser (JSON.stringify, json.dumps) and never build JSON by string concatenation.
Converting at the boundary
When you do not control the producer — a pasted LLM answer, a partner's export, a config file from another tool — converting at your boundary is legitimate, with one discipline: the conversion must be inspectable. A converter that silently rewrites a payload can turn a producer bug into corrupted production data without a trace. That is why the tool above returns a Repair Report next to the output: every removed comma and converted quote is a row you can read, download, and attach to the ticket that says "the export from system X is not JSON".
Frequently asked questions
Why are trailing commas illegal in JSON when JavaScript allows them?
JSON is a fixed, deliberately small grammar from 2001-era data interchange; JavaScript object syntax has since grown conveniences (trailing commas, single quotes, unquoted keys) that JSON never adopted. A strict JSON parser must reject them — which is why data copied out of JS/Python code so often fails as JSON.
Are single-quoted strings ever valid JSON?
No. JSON strings are double-quoted only, with a specific escape set. Single-quoted strings come from JavaScript literals, Python dicts, and hand-written config. Converting them is deterministic — the one subtlety is escapes: an apostrophe written as \' inside a single-quoted string becomes a plain apostrophe, which the repair report lists.
What about unquoted keys and comments?
Same family, same story: legal in JavaScript objects (keys) and in JSONC/JSON5 (comments), illegal in JSON. If your data source consistently produces them, your source is emitting a JSON-adjacent dialect — fine to convert at the boundary, better to fix at the producer.