JSONC is JSON plus comments (// and /* */). Whether it also allows trailing commas depends on the parser. It is the format of VS Code settings files and tsconfig.json. JSON5 is a superset of JSON that borrows syntax from ECMAScript 5.1: unquoted keys, single-quoted strings, trailing commas, hex numbers, comments and more.
Neither can go straight into JSON.parse or Python’s json.loads. Both throw at the first comment or other non-JSON syntax. This guide shows how to tell which format a file is, what the errors look like, and how to turn either one into standard JSON.
JSON vs JSONC vs JSON5: the differences
| Feature | JSON (RFC 8259) | JSONC | JSON5 |
|---|---|---|---|
// and /* */ comments | No | Yes | Yes |
| Trailing commas | No | Depends on the parser (see below) | Yes, one per object or array |
| Unquoted keys | No | No | Yes |
| Single-quoted strings | No | No | Yes |
| Strings across lines (escaped newline) | No | No | Yes |
Hex numbers (0x1F) | No | No | Yes |
.5, 5., leading + | No | No | Yes |
Infinity, NaN | No | No | Yes |
Binary numbers (0b101) | No | No | No |
| Specification | RFC 8259 / ECMA-404 | No formal standard; defined in practice by VS Code and jsonc-parser | JSON5 spec 1.0.0 |
Built-in JSON.parse / json.loads | Yes | No | No |
Sources: the JSON5 spec, the VS Code JSON docs and RFC 8259. We also ran JSON5.parse('{a: 0b101}') with json5 2.2.3, and it fails with JSON5: invalid character 'b' at 1:6.
JSON5 feels like a JavaScript object literal. JSONC is plain JSON that tolerates comments: keys must still be double-quoted, and so must strings.
A JSON5 file, config.json5:
// dev config
{
name: 'go-tools',
port: 0x1F90, // 8080 in hex
tags: ['json', 'json5',],
}
A JSONC file, tsconfig.json:
{
// strict type checking
"compilerOptions": {
"strict": true,
"target": "ES2022", /* modern output */
},
"include": ["src"],
}
Trailing commas in JSONC depend on the parser
JSONC has no official spec. Microsoft introduced it informally for VS Code’s configuration files and shipped jsonc-parser alongside it. A community draft at jsonc.org is trying to formalize it, and it says only that parsers “MAY support trailing commas”. Real tools disagree:
| Parser or tool | Trailing comma | Source |
|---|---|---|
| VS Code, JSON with Comments mode | Accepted, with a warning | VS Code docs |
jsonc-parser 3.3.1, default options | Reported as PropertyNameExpected / ValueExpected errors, but a value is still returned | Run below |
jsonc-parser 3.3.1, allowTrailingComma: true | Accepted | Run below |
TypeScript 5.9.3 (tsc -p) | Accepted | Run on the tsconfig above |
Deno (deno.jsonc) | Accepted | Deno configuration docs |
If you need a file that every JSONC reader accepts, leave trailing commas out.
Which format is your file?
The extension alone won’t tell you: a .json file can still be parsed as JSONC or JSON5. Check this table, then the docs of the tool that reads the file.
| File | Format | Notes | Source |
|---|---|---|---|
tsconfig.json, jsconfig.json, tsconfig.*.json | JSONC | VS Code opens them in JSONC mode; tsc 5.9.3 accepts comments and trailing commas | VS Code source (typescript-basics), our run |
.vscode/settings.json, tasks.json, launch.json | JSONC | Listed as JSON with Comments files | VS Code docs |
devcontainer.json | JSONC | The spec calls it “a JSON with Comments file” | Dev Container spec |
deno.jsonc | JSONC | “with deno.jsonc you can add comments and trailing commas” | Deno docs |
babel.config.json, .babelrc.json | JSON5, despite the .json extension | Babel parses them as JSON5; VS Code highlights them as JSONC | Babel docs, VS Code source |
renovate.json5, .renovaterc.json5 | JSON5 | renovate.json also accepts JSONC | Renovate docs |
Any *.json5 file | JSON5 | — | — |
package.json | Strict JSON | npm: “It must be actual JSON, not just a JavaScript object literal.” | npm docs, our run |
Babel does not look for a babel.config.json5 file: .json5 is not among its documented extensions. The .json variants are what it reads as JSON5.
The errors you’ll see, verbatim
We fed two small files to each runtime. comment.json has a comment:
{
// dev server port
"port": 8080
}
trailing.json has a trailing comma:
{
"port": 8080,
}
Node.js 26.10.0, JSON.parse (Chrome Headless Shell 156 gives the same text, since both use V8):
comment.json -> SyntaxError: Expected property name or '}' in JSON at position 4 (line 2 column 3)
trailing.json -> SyntaxError: Expected double-quoted property name in JSON at position 18 (line 3 column 1)
Python 3.13.5, json.loads:
comment.json -> json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 2 column 3 (char 4)
trailing.json -> json.decoder.JSONDecodeError: Illegal trailing comma before end of object: line 2 column 15 (char 16)
jq 1.7:
comment.json -> jq: parse error: Invalid numeric literal at line 2, column 5
trailing.json -> jq: parse error: Expected another key-value pair at line 3, column 1
npm 11.19.1, with a // comment line in package.json:
npm error code EJSONPARSE
npm error JSON.parse Invalid package.json: JSONParseError: Expected property name or '}' in JSON at position 4 (line 2 column 3) while parsing near "{\n // comment\n \"name\":..."
npm error JSON.parse Failed to parse JSON data.
npm error JSON.parse Note: package.json must be actual JSON, not just JavaScript.
How to read them:
position 4 (line 2 column 3)points at the first/of the comment. When the error lands at the start of a line that begins with//or/*, the file is almost certainly JSONC or JSON5.- For trailing commas, V8 and Python point at different places. V8 reports the closing
}(line 3), while Python 3.13.5 reports the comma itself (line 2, column 15). Other versions may word them differently; the text above is exactly what these versions printed. - If the error quotes a character you can’t see, as in Node 26’s
Unexpected token '', "{}" is not valid JSON(both quotes actually hold an invisible U+FEFF), the file most likely starts with an invisible byte-order mark rather than a comment. See UTF-8 BOM and JSON parse errors.
Convert JSONC or JSON5 to standard JSON
Converting drops every comment, because JSON has nowhere to keep them. Keep the commented file as the source and treat the .json output as a generated artifact.
Node.js: JSON5 to JSON with json5
// json5-to-json.mjs (npm install json5)
import { readFileSync, writeFileSync } from 'node:fs';
import JSON5 from 'json5';
const data = JSON5.parse(readFileSync('config.json5', 'utf8'));
writeFileSync('config.json', JSON.stringify(data, null, 2) + '\n');
Running it with json5 2.2.3 on the JSON5 example above produces this config.json:
{
"name": "go-tools",
"port": 8080,
"tags": [
"json",
"json5"
]
}
Node.js: JSONC to JSON with jsonc-parser
jsonc-parser is Microsoft’s parser for JSON with comments. Its parse() doesn’t throw on syntax errors. It collects problems in an errors array and still returns a best-effort value, so you have to check that array yourself:
// jsonc-to-json.mjs (npm install jsonc-parser)
import { readFileSync } from 'node:fs';
import { parse, printParseErrorCode } from 'jsonc-parser';
const errors = [];
const data = parse(readFileSync('tsconfig.json', 'utf8'), errors, {
allowTrailingComma: true,
});
if (errors.length > 0) {
for (const e of errors) console.error(printParseErrorCode(e.error), 'at offset', e.offset);
process.exit(1);
}
console.log(JSON.stringify(data, null, 2));
With jsonc-parser 3.3.1 and the tsconfig example above, this prints clean JSON and exits 0. Leave out allowTrailingComma: true and the same file produces PropertyNameExpected and ValueExpected at offsets 117 and 142: the } right after each trailing comma.
Python: the json5 package
The standard library json module has no option for comments. The json5 package reads JSON5, and therefore JSONC too, since comments and trailing commas are both legal JSON5:
# pip install json5
import json
import json5
with open("tsconfig.json", encoding="utf-8") as f:
data = json5.load(f)
print(json.dumps(data, indent=2, ensure_ascii=False))
Tested with Python 3.13.5 and json5 0.17.3, it prints the same JSON as the Node version.
Command line: the json5 CLI
The json5 npm package includes a CLI that converts to JSON and validates. It also reads JSONC files:
npx json5 config.json5 # compact JSON to stdout
npx json5 -s 2 -o config.json config.json5 # indented, written to a file
npx json5 -v tsconfig.json # validate only; exit code 1 on a syntax error
Because -v exits with code 1 on a syntax error, the same command works as a CI step that checks hand-edited JSON5 or JSONC files.
jq is no help here: as shown above, jq 1.7 stops at the first comment.
Watch out for Infinity and NaN
JSON5 allows Infinity and NaN, but JSON has no way to write them, and the two languages handle that differently:
JSON.stringify(JSON5.parse('{a: Infinity, b: NaN}'));
// '{"a":null,"b":null}' (silently becomes null)
json.dumps(json5.loads('{a: Infinity, b: NaN}'))
# '{"a": Infinity, "b": NaN}' (output that is not valid JSON)
json.dumps(json5.loads('{a: Infinity}'), allow_nan=False)
# ValueError: Out of range float values are not JSON compliant: inf
If a JSON5 file can contain them, pass allow_nan=False in Python, or check for them before you convert. Single-quoted JSON5 strings that contain " or backslashes are re-escaped by JSON.stringify. The rules are in the JSON string escaping guide.
Validate the converted JSON
After converting, paste the output into the JSON Formatter to validate and pretty-print it. It runs in your browser.
Note that the formatter accepts strict JSON only. It parses with the browser’s JSON.parse, so a JSONC or JSON5 file pasted as is fails with a syntax error and the line and column where parsing stopped. Convert first, then validate.
When not to use JSONC or JSON5
- API payloads and data exchange. RFC 8259 says a JSON generator “MUST strictly conform to the JSON grammar”. The receiving end is usually
JSON.parseorjson.loads, and both reject comments. package.json. npm requires strict JSON. A single comment makes npm commands such asnpm runfail withEJSONPARSE.- Files read by tools you don’t control. Node’s
require('./tsconfig.json')uses the strict JSON parser and fails on a commented tsconfig (SyntaxError: …tsconfig.json: Expected property name or '}' in JSON at position 4). Any script that reads a JSONC file needs a JSONC parser. - A
.jsonfile that silently became JSONC. Renovate’s docs recommend a.jsoncfile over a.jsonfile with comments, since the latter “can cause issues with editors and syntax highlighting”. An explicit extension tells every tool what to expect.
If you’re choosing a config format from scratch and want comments everywhere, TOML and YAML support them natively. See TOML vs JSON vs YAML.
Frequently asked questions
What is the difference between JSON5 and JSONC?
JSONC is standard JSON plus // and /* */ comments; trailing commas depend on the parser. JSON5 goes further with ES5.1 syntax: unquoted keys, single quotes, hex numbers, Infinity/NaN and trailing commas. A valid JSONC file is usually valid JSON5, but not the other way round.
Can I use JSON5 or JSONC in production APIs?
No. Use them for hand-edited config files and send strict JSON (RFC 8259) over the wire. Clients parse responses with JSON.parse or json.loads, which reject comments, unquoted keys and trailing commas.
Does VS Code support JSON5 natively?
Not out of the box. VS Code’s built-in JSON extension registers languages such as json, jsonc and jsonl, but not json5, so .json5 files need a marketplace extension for highlighting. JSONC is built in: settings, tasks.json, launch.json and tsconfig.json all open in JSON with Comments mode.
How do I convert JSON5 to standard JSON?
Run npx json5 -s 2 -o config.json config.json5, or in code, JSON.stringify(JSON5.parse(text), null, 2). Comments are dropped. Check for Infinity and NaN first, because JSON.stringify turns them into null.
Does tsconfig.json allow comments and trailing commas?
Yes for TypeScript itself: tsc 5.9.3 accepted a tsconfig with both in our test, and VS Code opens tsconfig files in JSONC mode. Scripts that read tsconfig with plain JSON.parse or require() will fail on the comments, so they need a JSONC parser.
Is JSONC the same as “JSON with Comments”?
Yes. “JSON with Comments” is the name of VS Code’s language mode, and jsonc is its language ID and file extension. There is no official standard; jsonc.org hosts a community draft based on what jsonc-parser accepts by default.
For more browser-based tools, see the Essential Developer Tools Guide.