JSONC in one paragraph
JSONC (“JSON with Comments”) is ordinary JSON plus two conveniences: // line comments and /* … */ block comments, and a trailing comma after the last item of an object or array. Microsoft introduced it for VS Code’s settings.json and launch.json, and it is now used by tsconfig.json, jsconfig.json, devcontainer.json, .eslintrc.json, Deno’s deno.jsonc, Biome and Turborepo. Strict JSON readers, from JSON.parse to Python’s json module and jq, reject both conveniences, so a config that works in your editor can fail in a script or a CI step.
What the converter changes, and what it does not
Only the two JSONC additions are touched. Comments are removed wherever they appear, including between a key and its value; text that merely looks like a comment inside a string, such as "https://example.com/*" or a glob like "**/*.ts", is left alone. A comma is removed when the next meaningful character is } or ], even if a comment sits in between.
Everything else is passed through exactly: key order, duplicate keys, string escapes and number spellings, so 1.50, 1e3 and 64-bit integers are not rewritten. The result is pretty-printed with the indent you choose in the toolbar, and Sort keys works too. An info note reports how many comments and trailing commas were removed, so you can tell at a glance whether the file was already strict.
Errors point at your original lines
Comments are blanked out in place rather than deleted, so every character keeps its position. When the remaining text is not valid JSON, the error shows the line and column in the file you pasted, not in some intermediate version. A missing comma between two settings, an unclosed /*, or a stray character are all reported where they are.
JSONC deliberately stops at comments and trailing commas. Unquoted keys, single-quoted strings, hexadecimal numbers, Infinity and NaN belong to JSON5; when the converter meets them it says so and points you to the JSON5 to JSON converter. Keeping the two apart means a typo in a tsconfig is reported as a mistake instead of being quietly accepted.
Typical uses
- Read a value from
tsconfig.jsonin a shell script: convert, then pipe the strict JSON intojq '.compilerOptions.paths'. - Merge editor settings from several machines with a JSON diff tool that does not understand comments.
- Send a Dev Container or VS Code configuration to an API or store it in a database column that validates JSON.
- Check a hand-edited config before committing: if it converts, the structure is sound.
The comments are gone in the output, so treat the JSONC file as the source and regenerate the strict copy when it changes. To tidy a JSONC file while keeping its comments, use the JSON5 / JSONC formatter instead; background on the dialects is in the guide to JSON with comments.
Examples
tsconfig.json with explanations
Line and block comments disappear along with three trailing commas; the "**/.spec.ts" glob is untouched even though it contains /.
{
"compilerOptions": {
"target": "ES2023",
"module": "NodeNext",
// Keep these in sync with eslint
"strict": true,
"noUncheckedIndexedAccess": true,
"paths": {
"@app/*": ["./src/*"], /* path alias */
},
},
"exclude": ["dist", "**/*.spec.ts",],
}{
"compilerOptions": {
"target": "ES2023",
"module": "NodeNext",
"strict": true,
"noUncheckedIndexedAccess": true,
"paths": {
"@app/*": [
"./src/*"
]
}
},
"exclude": [
"dist",
"**/*.spec.ts"
]
}
devcontainer.json
A typical Dev Containers file: the header comment and the comment after an extension ID are removed, and the result can be read by jq.
// Dev Container for the API service
{
"name": "api",
"image": "mcr.microsoft.com/devcontainers/typescript-node:22",
"forwardPorts": [3000, 9229],
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint", // linting
"esbenp.prettier-vscode",
],
},
},
"postCreateCommand": "npm ci",
}{
"name": "api",
"image": "mcr.microsoft.com/devcontainers/typescript-node:22",
"forwardPorts": [
3000,
9229
],
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
},
"postCreateCommand": "npm ci"
}
Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
Missing comma after line 4Explained | Two settings are missing the comma between them; common after deleting or commenting out a line. | Add the comma at the end of the line the error points to. |
This /* comment is never closed | A block comment was opened but its */ is missing, often after commenting out a section. | Add */ where the comment should end. |
Object keys must be in double quotes: found nameExplained | The file uses unquoted keys, which is JSON5 syntax rather than JSONC. | Quote the key, or convert the file with JSON5 to JSON instead. |
Strings must use double quotes, not single quotesExplained | A value is written as ‘text’, which JSONC does not allow. | Use double quotes, or treat the file as JSON5. |
Frequently asked questions
What is the difference between JSONC and JSON5?
JSONC adds only comments and trailing commas to JSON. JSON5 goes further with unquoted keys, single quotes, hex numbers and more. This page handles JSONC strictly; the JSON5 converter accepts the larger syntax.
Does it change my numbers or key order?
No. Values, escapes and key order are copied exactly; only comments and trailing commas are removed and the layout is re-indented.
Is tsconfig.json really not valid JSON?
Correct. TypeScript reads it with a JSONC parser, so comments and trailing commas work there but break strict tools like jq or JSON.parse.
Can I keep the comments?
Strict JSON has no comment syntax. Keep the original JSONC file, or use the JSON5 / JSONC formatter, which preserves comments.