Comments in JSON: Why They Fail, and What JSONC and JSON5 Actually Change
The awkward part is not that JSON forbids comments. It is that the error you get says nothing about comments, and is identical to the one a trailing comma produces — so the message sends you looking in the wrong place.
The short answer
JSON has no comments. The grammar has no production for one, so // and /* */ are simply unexpected characters — there is nothing to disable and no parser option to set.
The part that wastes time is the error. A comment produces Expected property name or '}' in JSON at position 4 (line 2 column 3) — a message about property names that never mentions comments, and that a trailing comma produces too.
What each form actually does
| Input | JSON.parse | JSON5 |
|---|---|---|
| { // note "a": 1 } | Expected property name or '}' in JSON at position 4 (line 2 column 3) | Accepted |
| { /* note */ "a": 1 } | Expected property name or '}' in JSON at position 4 (line 2 column 3) | Accepted |
| { "a": 1 } // done | Unexpected non-whitespace character after JSON at position 11 (line 1 column 12) | Accepted |
| { # note "a": 1 } | Expected property name or '}' in JSON at position 4 (line 2 column 3) | Rejected — invalid character '#' |
| { "_comment": "note", "a": 1 } | Valid | Accepted |
Two things worth noticing. A comment after the document gives a different message, because by then the value has parsed and the leftover text is the surprise. And # is rejected by both — it is a comment character in YAML and TOML, not in anything JSON-shaped.
Why the message misleads
After {, the only legal things are a property name or a closing brace. A / is neither, so the parser reports what it wanted rather than what it found — and it wanted a property name.
That is why the same sentence appears for a trailing comma and for an unquoted key: three different mistakes, one parser state. If you are staring at a message about property names and every key looks correctly quoted, check the line above for a comment.
JSON, JSONC, and JSON5
| Format | Comments | Where you meet it | Trade-off |
|---|---|---|---|
| JSON | None | Everywhere | RFC 8259 has no production for a comment. |
| JSONC | // and /* */ | VS Code settings, tsconfig.json | Adds comments and nothing else. Strip them and the file is valid JSON. |
| JSON5 | // and /* */ | Opt-in, via the json5 package | Also adds trailing commas, unquoted keys, single quotes. A larger change. |
The distinction that matters when choosing: JSONC adds comments and stops there, so stripping them leaves valid JSON. JSON5 is a broader dialect, and a JSON5 file is generally not valid JSON even with the comments removed.
What to do instead
- Use a comment-shaped keyA property such as "_comment" is ordinary JSON that every parser accepts. It travels anywhere, and the cost is that it is data — it appears in your object and in anything that iterates the keys.
- Use JSONC where the consumer already supports itEditor and tooling config files are the natural home. It is the smallest possible extension: comments and nothing else.
- Use JSON5 when you control the parserReasonable for a config file read by your own code. Not reasonable for an API payload, because the receiver almost certainly uses a standard parser.
- Strip comments before parsingCommon in build steps. Doing it with a regular expression is where it goes wrong — a // inside a string value, such as a URL, is not a comment, and a naive strip will corrupt the document.
{
"_comment": "Staging only. Rotate the key before release.",
"endpoint": "https://staging.example.com",
"timeout": 30
}That parses everywhere, today, with no tooling change. It is not elegant, and it is the only option that needs nothing from the consumer.
On stripping comments with a regular expression, one example is enough to show the danger:
{ "url": "https://example.com" }The // there is inside a string. A strip that does not track string state will cut the value in half and leave a document that is still valid JSON but quietly wrong — which is worse than one that fails to parse.
Check a document
Pasting into the JSON Formatter reports the position and line where parsing stopped, which is the fastest way to find the comment the message did not name.
It parses strict JSON only. It does not accept JSONC or JSON5, does not strip comments, and will not repair the document — a file with comments produces the error and no output. Parsing runs in your browser, so a config with real values is not uploaded anywhere.
Measured with
- Node.js / V8 —
24.16.0 / 13.6 - JSON5 —
2.2.3 - DataToolsHQ JSON Formatter —
native JSON.parse (V8)
Error wording changes between releases. The rule underneath does not: JSON has no comments, in every version and every parser.