JSON vs JSON5

Updated: August 8, 2026

JSON5 adds back the conveniences JSON deliberately removed. That makes it better for configuration and worse for everything else.

The Problem JSON5 Solves

JSON was designed for machines to exchange, and its strictness serves that purpose well. But it steadily leaked into a job it was not designed for: configuration files that humans write and maintain. There, the missing conveniences hurt.

You cannot explain why a setting exists, because there are no comments. You cannot reorder a list without adjusting commas, because trailing commas are forbidden. And you must quote every key, even when the keys are plain identifiers.

JSON5 is a superset that restores those conveniences, borrowing from ES5 syntax. The same file, in both formats:

// JSON — valid, but nothing explains itself
{
  "port": 8080,
  "timeoutMs": 30000,
  "replicas": ["db-r1", "db-r2"]
}
// JSON5 — annotated and easier to edit
{
  port: 8080,              // unquoted key, and a comment
  timeoutMs: 30_000,       // numeric separator for readability

  /* Read replicas. Order matters: the first is preferred. */
  replicas: [
    'db-r1',               // single quotes are fine
    'db-r2',               // trailing comma is fine
  ],
}

What JSON5 Adds

FeatureJSONJSON5
CommentsNoYes — line and block
Trailing commasNoYes
Unquoted keysNoYes, for valid identifiers
Single-quoted stringsNoYes
Multi-line stringsNoYes, via line continuation
Hexadecimal numbersNoYes — 0xFF
Leading / trailing decimal pointNoYes — .5 and 5.
Infinity and NaNNoYes
Explicit plus signNoYes — +1

Note that several of these are exactly the mistakes listed on the common JSON errors page. That is not a coincidence — people write trailing commas and unquoted keys in JSON precisely because those are legal everywhere else they type, and JSON5 accepts the habit rather than fighting it.

The Superset Direction Matters

JSON5 is a strict superset of JSON, and the asymmetry is the whole practical story:

Every JSON document        → parses as JSON5   ✓
A JSON5 document using
its added features         → parses as JSON    ✗

So a JSON5 parser can read your existing JSON files unchanged, but the moment you use a comment or a trailing comma, that file is no longer readable by anything expecting JSON — which is every browser, every standard library, and every tool you did not specifically configure.

This is why JSON5 has stayed a configuration format rather than an interchange one. Its adoption cost is not the syntax; it is that every consumer needs a non-standard parser.

JSONC: The Smaller Middle Ground

JSONC — "JSON with Comments" — adds only comments and trailing commas, and nothing else. It is far more widely deployed than JSON5, largely because Microsoft uses it:

// tsconfig.json is JSONC, despite the .json extension
{
  "compilerOptions": {
    // Target modern runtimes; we do not support IE
    "target": "ES2022",
    "strict": true,        // trailing comma is tolerated here
  }
}

This explains a genuinely confusing situation: tsconfig.json, .vscode/settings.json and launch.json all accept comments, while the same syntax in package.json breaks npm. The extension is identical; the parser is not. If a JSON file in your project tolerates comments, it is JSONC and something specific is reading it.

JSONC is the more conservative choice of the two. It fixes the two things that actually hurt in configuration files and leaves JSON's other rules alone, so a document is easier to convert back if you need to.

Using JSON5

npm install json5
import JSON5 from "json5";

// Mirrors the built-in JSON API
const config = JSON5.parse(text);
const output = JSON5.stringify(config, null, 2);

// Reading a .json5 config file
import { readFileSync } from "node:fs";
const config = JSON5.parse(readFileSync("config.json5", "utf8"));

Give JSON5 files a .json5 extension. Naming one .json is asking for trouble — any generic tool that opens it will fail, and the error will not obviously point at the file format.

Parsers exist for Python (json5), Go, Rust and others, but none is in a standard library. That dependency is the real cost of adopting the format.

Getting Comments Without Leaving JSON

If you only want to annotate a config file and would rather not add a parser, two approaches work in plain JSON.

A comment key — legitimate JSON, since it is just a string value:

{
  "_comment": "Timeout is 30s to match the upstream gateway.",
  "timeoutMs": 30000
}

Or point at a schema, which puts the documentation somewhere better than a comment and gives you editor autocomplete and validation at the same time:

{
  "$schema": "https://example.com/schemas/app-config.json",
  "timeoutMs": 30000
}

The schema approach is usually the better answer. Descriptions live with the field definitions, editors surface them on hover, and invalid values are flagged as you type — none of which a comment does.

Choosing

JSON

Anything crossing a network, anything a program generates, anything a third party consumes. The default, and correctly so.

JSONC

Project configuration where comments would help and your toolchain already supports it — TypeScript and VS Code files especially.

JSON5

Hand-maintained config where the extra syntax genuinely earns its dependency. Consider whether YAML or TOML fits better first.

One rule regardless of choice: never emit JSON5 or JSONC from an API. Consumers expect application/json, and a response containing a comment will fail in every standard client with an error that gives no hint of the real cause.

Frequently Asked Questions

Is JSON5 valid JSON?

No, and the direction matters. JSON5 is a superset, so every JSON document is valid JSON5 — but a JSON5 document using comments, trailing commas or unquoted keys will be rejected by a standard JSON parser.

What is the difference between JSON5 and JSONC?

JSONC is 'JSON with Comments' — it adds only comments and trailing commas, and is what VS Code uses for settings.json and tsconfig.json. JSON5 goes considerably further, adding unquoted keys, single quotes, hexadecimal numbers, multi-line strings and more.

Can I use JSON5 for an API?

You should not. Consumers expect application/json, and no browser or standard library parses JSON5 natively, so every client would need an extra dependency. JSON5 is for files humans edit, not for data crossing a network.

Why does my tsconfig.json allow comments when JSON does not?

Because tsconfig.json is JSONC rather than JSON, despite the extension. The TypeScript compiler and VS Code use a parser that tolerates comments and trailing commas. A generic JSON parser reading the same file will fail.

Related Resources

Related Resources