Why JSON Has No Comments
JSON was designed by Douglas Crockford in 2001 as a minimal data-interchange format. Comments were deliberately excluded. Crockford's reasoning: he saw developers using comments in JSON config files to add parser directives — "parse this differently" — which turned comments into a second channel for instructions. Removing comments kept the format clean and unambiguous.
The result is that JSON is a data format, not a config format. But developers use it for config anyway, which is why the lack of comments is felt every day.
What Happens If You Add Comments Anyway?
{
// This is a database URL
"db": "postgres://localhost/myapp",
"port": 3000
}Every standard JSON parser throws a syntax error. JSON.parse() in JavaScript, Python's json.loads(), and Go's json.Unmarshal() all reject this immediately.
Option 1: Use a "_comment" Key
The most portable workaround — works with any JSON parser, no tooling required:
{
"_comment": "Database connection config — use env vars in production",
"db": "postgres://localhost/myapp",
"port": 3000
}Pros: Valid JSON, works everywhere. Cons: It's a data field, not a real comment — it shows up in parsed output. Use a consistent key name and strip it programmatically if needed.
Option 2: JSONC (JSON with Comments)
JSONC is a superset of JSON used by VS Code for all its config files (settings.json, launch.json, tasks.json, extensions.json). It adds single-line and multi-line comments:
// tsconfig.json supports JSONC
{
"compilerOptions": {
// Enable strict null checks
"strict": true,
/* Path aliases for cleaner imports */
"paths": {
"@/*": ["./src/*"]
}
}
}Where JSONC is used: VS Code configs (.vscode/settings.json), some Azure and Microsoft tooling.
Parsing JSONC in Node.js:
import { parse } from "jsonc-parser";
const config = parse(`
{
// Hello
"port": 3000
}
`);
console.log(config.port); // 3000Option 3: JSON5
JSON5 is a more ambitious superset that adds multiple quality-of-life improvements alongside comments:
{
// Single-line comment
/* Multi-line
comment */
name: "Ravi", // Unquoted keys
message: "Hello
World", // Multi-line strings
hex: 0xDECAF, // Hex numbers
trailing: "comma", // Trailing commas allowed
}Where JSON5 is used: Babel config (babel.config.json5), some bundlers, and projects that want human-friendly config files.
Parsing JSON5:
import JSON5 from "json5";
const config = JSON5.parse(fs.readFileSync("config.json5", "utf8"));Option 4: Switch to YAML or TOML for Config
If you're using JSON purely for configuration (not data interchange), YAML and TOML both have native comment support:
# Database connection — use env vars in production
db: postgres://localhost/myapp
port: 3000# Database connection
db = "postgres://localhost/myapp"
port = 3000Both are well-supported in every major language. YAML is dominant in infrastructure (Docker, Kubernetes, GitHub Actions). TOML is favoured in Rust (Cargo.toml) and Python (pyproject.toml).
The Right Choice
- API data exchange? Use plain JSON. Comments don't belong in wire format.
- VS Code settings or similar tooling? Use JSONC — it's already supported.
- Application config file? Use YAML, TOML, or JSON5 for human readability.
- Quick workaround without new parsers? Use a "_comment" key.
Validate your JSON at JSONKit's validator to confirm your file is comment-free and parse-ready before shipping.