Comments in JSON: JSONC, JSON5 and Safe Stripping

Paste a tsconfig.json into a strict JSON parser and it fails on the first comment. That is not a bug in either tool: JSON has no comments, and the files that use them are written in a related format. This guide sorts out which is which.

Why JSON has no comments

The JSON specifications (RFC 8259 and ECMA-404) define no comment syntax at all. Douglas Crockford, who popularised JSON, has explained that he removed comments early on because people were using them to carry parsing directives, which would have broken interoperability between parsers. His suggested workaround was to write comments anyway and run the file through a minifier such as JSMin before handing it to a JSON parser.

So when a parser reports an unexpected / character, it is behaving correctly. The question is which comment-friendly dialect the file was really written in, and whether the consumer of the file understands that dialect.

JSONC: JSON with comments

JSONC is plain JSON plus // line comments and /* */ block comments. It was popularised by Visual Studio Code, whose own settings files use it, and Microsoft’s jsonc-parser library is the reference implementation most tools build on. Many JSONC parsers also tolerate trailing commas, but that is a parser option rather than a guarantee, so do not rely on it for files other tools will read.

Files that are commonly JSONC:

  • tsconfig.json and jsconfig.json (TypeScript’s parser accepts comments and trailing commas)
  • VS Code settings.json, launch.json, tasks.json and .devcontainer/devcontainer.json
  • Windows Terminal settings, deno.jsonc, and .eslintrc.json in ESLint’s legacy configuration

Everything else in JSONC is identical to JSON: keys and strings use double quotes, and there are no new value types.

{
  // compiler settings
  "compilerOptions": {
    "target": "ES2022", /* modern runtimes only */
    "strict": true
  }
}

JSON5: JSON for humans

JSON5 goes further and borrows syntax from ECMAScript 5.1 object literals. On top of comments it allows:

  • trailing commas in objects and arrays
  • unquoted keys that are valid identifiers, such as name: 'app'
  • single-quoted strings, and strings continued across lines with a backslash at the line end
  • hexadecimal numbers (0xFF), leading or trailing decimal points (.5, 5.), an explicit plus sign, and Infinity and NaN
  • additional whitespace characters
// config
{
  name: 'app',
  port: 8080,
  hosts: ['a.example.com', 'b.example.com',],
  ratio: .5,
}

JSON5 is used for Babel’s .babelrc files, Renovate configuration (renovate.json5), some Chromium build files and many hand-edited application configs. Because it accepts more syntax, a JSON5 parser reads every JSON document, but a JSON5 file is generally not readable by a JSON or JSONC parser.

Stripping comments safely

When a consumer only accepts strict JSON, remove the comments before parsing. The trap is doing it with a regular expression: a pattern like //.* also deletes the second half of "https://example.com", silently corrupting a URL inside a string. Comment removal has to understand string literals, which means using a tokenizer:

  • JavaScript: jsonc-parser (parse with error reporting), strip-json-comments, or JSON5.parse from the json5 package
  • Python: the json5 package, or commentjson for JSONC-style files
  • Go: github.com/tailscale/hujson, which standardises JSONC with trailing commas
  • Command line: npx strip-json-comments-cli, or a JSON5 parser piped into jq

If you control the format, consider whether the reader can accept JSONC or JSON5 directly; most configuration loaders can.

In PasteKit, the JSON5 / JSONC formatter has a Variant option (Auto-detect, JSON5, or JSONC (JSON with comments)), a Quote keys option (As written, Only where needed, or All or none per object) and a Trailing commas option (Remove, or Add to multi-line objects and arrays). Comments are preserved when formatting. The JSON5 to JSON converter produces strict JSON and drops the comments.

Choosing between JSONC and JSON5

If the file is read by a tool that already defines the format — TypeScript, VS Code, Babel, Renovate — use what that tool expects. For a new configuration format of your own, the decision comes down to who edits the file and which parsers must read it:

  • JSONC is the conservative choice. It looks exactly like JSON, so anyone can read it, and the only parser change is skipping comments. Every JSON5 parser can read it as well.
  • JSON5 is friendlier to type by hand (no quotes around keys, trailing commas, hex numbers), but files written in it look unfamiliar to people who know only JSON, and fewer languages have mature parsers.

Name files by what they contain. A .jsonc or .json5 extension tells editors and colleagues which rules apply; a .json file with comments in it is a trap for the next tool that reads it strictly. In VS Code you can still mark specific files as JSONC with the files.associations setting, which stops the editor from flagging their comments.

Keeping comments when tools rewrite the file

A subtle problem appears when programs edit configuration files. Most libraries parse into plain data, change it, and serialise it again — which silently deletes every comment and blank line. That is why some tools that “update your tsconfig” leave it stripped of explanations.

If you write such a tool, edit the text rather than the data. Microsoft’s jsonc-parser provides modify and applyEdits functions that compute minimal text edits for a change at a given path, leaving comments and formatting untouched. For JSON5 there are similar edit-preserving libraries, or you can fall back to targeted text replacement for simple cases.

Conventions that avoid comments altogether

Sometimes you cannot change the parser — package.json is read by npm with a strict JSON parser, and the same is true of most REST APIs. Common workarounds:

  • A comment key. npm tolerates an extra top-level key named "//" holding an explanatory string, and some projects use "_comment" or "$comment" keys. These are data, not comments, so they can collide with schemas that forbid unknown properties.
  • JSON Schema descriptions. If the file has a schema, put documentation in the schema’s description fields. Editors show them as hover text, which is better than comments because every file gets them.
  • Switch format. If people edit the file often and need explanations inline, YAML or TOML may be the better choice; both support # comments natively.

Frequently asked questions

Does JSON allow comments?

No. Neither RFC 8259 nor ECMA-404 defines any comment syntax, so strict parsers such as JSON.parse reject // and /* */.

What is the difference between JSONC and JSON5?

JSONC is JSON plus comments (and often trailing commas). JSON5 also allows unquoted keys, single quotes, hex numbers, Infinity and NaN, and other ECMAScript literal syntax.

Can I put comments in package.json?

No. npm parses it as strict JSON. A “//” key with a string value is the conventional workaround.

Why is a regex a bad way to strip JSON comments?

It cannot tell comments from text inside strings, so it breaks values such as URLs that contain //. Use a tokenizer-based stripper instead.

Is tsconfig.json valid JSON?

Often not. TypeScript reads it with a lenient parser that accepts comments and trailing commas, so treat it as JSONC.

Related