# JSON Syntax Reference
JSON (JavaScript Object Notation) is a strict, minimal data format — far stricter than the JavaScript object literals it resembles. This sheet covers the full grammar, the escape sequences, and the exact ways JSON5/JSONC relax the rules, since "my JSON won't parse" is almost always one of these differences.
| Type | Example | Notes |
|---|---|---|
| String | `"hello"` | Double quotes only, never single quotes |
| Number | `42`, `-3.14`, `1.5e10` | No leading zeros (`01` is invalid), no `NaN`/`Infinity` |
| Boolean | `true`, `false` | Lowercase, unquoted |
| Null | `null` | Lowercase, unquoted |
| Object | `{"key": "value"}` | Keys must be double-quoted strings |
| Array | `[1, 2, 3]` | Mixed types allowed |
| Escape | Meaning |
|---|---|
| `\"` | Double quote |
| `\\` | Backslash |
| `\/` | Forward slash (optional — `/` is valid unescaped too) |
| `\n` | Newline |
| `\t` | Tab |
| `\r` | Carriage return |
| `\b` | Backspace |
| `\f` | Form feed |
| `\uXXXX` | Unicode code point (4 hex digits) |
| Feature | JSON | JSON5 | JSONC |
|---|---|---|---|
| Trailing commas | No | Yes | No |
| Comments (`//`, `/* */`) | No | Yes | Yes |
| Unquoted object keys | No | Yes (if valid identifier) | No |
| Single-quoted strings | No | Yes | No |
| Multi-line strings (`\` continuation) | No | Yes | No |
| Leading `+` on numbers | No | Yes | No |
| Hex numbers (`0xFF`) | No | Yes | No |
JSONC (used by tsconfig.json, VS Code settings) is plain JSON plus comments — nothing else. JSON5 is a much larger superset aimed at hand-written config files, not data interchange; don't feed JSON5 to a strict JSON.parse().
try {
const data = JSON.parse(rawInput);
} catch (e) {
console.error('Invalid JSON:', e.message);
}
Every JSON.parse() on untrusted or user-supplied input belongs in a try/catch — a malformed payload throws a SyntaxError, it doesn't return null.
JSON.stringify(data, null, 2); // 2-space indent
JSON.stringify(data, null, '\t'); // tab indent
JSON.stringify({ id: 1, password: 'secret', name: 'x' }, ['id', 'name']);
// -> {"id":1,"name":"x"}
The second argument can be an array of allow-listed keys instead of a replacer function.
const clone = JSON.parse(JSON.stringify(original));
Fast and dependency-free, but it has real gaps: undefined and functions are dropped entirely, Date objects become ISO strings, Map/Set serialize as an empty {} (silently losing every entry, not dropped as a key), and circular references throw a TypeError instead of cloning.
JSON.parse(raw, (key, value) => {
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
return new Date(value);
}
return value;
});
{"a": 1,} throws Unexpected token } in JSON.parse. This is the single most common "my config file won't load" bug when copy-pasting from JS source into a .json file.undefined, NaN, Infinity, and functions vanish silently on stringify: JSON.stringify({a: undefined, b: NaN}) produces {"b":null} — no error, just data loss. Check for these before you serialize if their absence would be a bug.// notes or / block / anywhere in a .json file fails to parse. If you need comments, either use JSONC-aware tooling explicitly or a JSON5 parser — never assume JSON.parse will skip them.{"a":1,"a":2} parses without error in most engines, silently keeping the last value. Don't rely on this — it's not guaranteed by the JSON spec (RFC 8259) which just says behavior is undefined.Number is a 64-bit float, so a 19-digit ID like a Snowflake or bigint from another language can silently round. Send large IDs as strings, or parse with a bigint-aware library.pattern keyword and most JSON validators.