JSON vs JSON5 vs JSONC
Comments, trailing commas, single quotes and unquoted keys are all legal JavaScript and all rejected by JSON. JSON5 and JSONC add them back — for files you edit, not for bytes you transmit.
By the Withuse team · Updated
What strict JSON refuses
We ran the eight things people most often try. Every one was rejected:
| Written as | JSON | JSONC | JSON5 |
|---|---|---|---|
{"a":1} // note | ❌ | ✅ | ✅ |
{"a":1,} | ❌ | ✅ | ✅ |
{'a':1} | ❌ | ❌ | ✅ |
{a:1} | ❌ | ❌ | ✅ |
{"a":0xFF} | ❌ | ❌ | ✅ |
{"a":.5} | ❌ | ❌ | ✅ |
{"a":NaN} | ❌ | ❌ | ✅ |
| multi-line string | ❌ | ❌ | ✅ |
The confusion is understandable: all eight are valid JavaScript, and JSON began as a subset of JavaScript syntax. It was deliberately made smaller. Comments in particular were removed on purpose — people had begun using them to carry parsing directives, which turns a data format into something every implementation interprets slightly differently.
The consolation is that these failures are loud. The parser stops and gives you a position. That puts them in a different category from the two silent failures — integer precision loss and duplicate keys — which parse cleanly and hand back wrong data.
Which extension is which
JSONC is JSON plus comments and trailing commas, and stops there. It is what Visual Studio Code accepts in settings.json and tsconfig.json, which is why the habit spreads through TypeScript projects and why people are then surprised when the same file fails elsewhere. It is a convention rather than a published standard.
JSON5 is a specification in its own right and goes much further: unquoted keys, single-quoted strings, hexadecimal numbers, leading and trailing decimal points, NaN and Infinity, multi-line strings, and explicit plus signs. It has implementations across many languages.
The rule that keeps this clean
Treat JSON5 and JSONC as authoring formats and strict JSON as the transmission format. Convert at the boundary — in your build step, or when the file is loaded — and the file a human edits keeps its comments while the bytes crossing a network stay parseable by everything.
Sending JSON5 over an API breaks the first consumer that uses its language's standard parser, and that is nearly all of them, plus every gateway and logging pipeline along the way. The extensions were never meant for the wire.
When the format is fixed
If you cannot change the format but need a note, add a key that marks itself as commentary — "_comment" is the common choice, and "$schema" has the side benefit that editors use it for completion and validation.
Be clear about the cost: that note is now data. It is transmitted, stored, and returned with everything else, and a strict schema validator may reject the unexpected property. Acceptable for a file that stays on disk; clutter for a payload that crosses a network.
Frequently asked questions
Does JSON support comments?
No. The grammar has no production for them, so JSON.parse rejects a document containing // or /* outright — we confirmed it raises rather than ignoring them. Douglas Crockford removed comments deliberately, on the grounds that people were using them to carry parsing directives, which turned a data format into something implementations had to interpret differently. The workaround people reach for is a dummy key such as "_comment", which is valid JSON but travels with the data and reaches every consumer. If you need genuine comments in a configuration file, use JSONC or JSON5 and convert before shipping the result anywhere. The dummy-key approach also breaks strict schema validation, which rejects properties the schema does not declare.
What exactly does JSON.parse reject?
We tested the eight things people most often try and all eight were refused: comments, a trailing comma, single-quoted strings, unquoted object keys, hexadecimal numbers, a leading decimal point such as .5, NaN, and a string broken across lines with a backslash. Every one of these is legal JavaScript, which is the source of the confusion — JSON looks like a subset of JavaScript syntax and largely is, but it was deliberately made smaller. The upside is that these failures are loud: the parser stops and reports a position, unlike the silent problems of precision loss and duplicate keys, which parse cleanly and hand back data that is simply wrong.
What is the difference between JSON5 and JSONC?
JSONC is JSON with comments and trailing commas, and nothing else — it is the format Visual Studio Code accepts in its settings and tsconfig files, which is why the habit spreads through TypeScript projects. JSON5 goes considerably further: unquoted keys, single-quoted strings, hexadecimal and leading-decimal numbers, NaN and Infinity, multi-line strings, and a plus sign on positive numbers. JSON5 is a published specification with implementations in many languages; JSONC is more a convention than a standard. Neither is JSON, and neither should be sent to a consumer expecting RFC 8259. Editor support differs too: JSONC is understood by VS Code out of the box, while JSON5 usually needs a plugin or a build step.
Can I send JSON5 over an API?
You should not. Any consumer using its language's standard JSON parser will reject the payload, and that includes almost every HTTP client, gateway and logging pipeline in the path. The extensions exist for files a human edits — configuration, fixtures, seed data — where comments and trailing commas genuinely reduce mistakes. The rule that keeps this clean is to treat JSON5 and JSONC as authoring formats and convert to strict JSON at the boundary, in the build step or on load. Then the file you edit stays readable and the bytes you transmit stay universally parseable. The conversion is a single function call in every language that has a JSON5 implementation.
How do I add a comment to a JSON file I cannot change the format of?
Add a key whose name marks it as commentary, such as "_comment" or "$schema". This is valid JSON so every parser accepts it, and the $schema convention has the additional benefit that editors will use it to offer completion and validation. The drawback is real: the value is data, so it is transmitted, stored and returned along with everything else, and a strict schema validator may reject the unexpected property. For a file that only ever lives on disk it is fine. For a payload crossing a network it is clutter that someone downstream will eventually have to handle, and it will be the person who did not know it was decorative.
References
Check whether a document is strict JSON with the formatter and validator, which also flags the silent failures. More tools at withuse.io/tools.