Skip to content

JSON Variants Explained

The JSON family compared — strict RFC 8259 JSON, JSON5, JSONC, and JSON Lines — by what each variant allows, forbids, and the parser quirks behind them.

The JSON family covers more than the wire format: strict RFC 8259 JSON for interchange, JSON5 and JSONC for hand-edited config, and JSON Lines for streaming. This table lists what each variant allows and forbids, plus the parser quirks that bite real code. Keep strict JSON on the wire and relax only in files you edit by hand.

Reference table · 26 entriesOpen the json-formatter tool →
26 of 26 rows
JSON (RFC 8259)
StringsDouble-quoted text with backslash escapes and \uXXXX; raw UTF-8 allowed outside ASCII.Single quotes, unescaped control characters (U+0000–001F), raw newlines.Every key and string value on the wire.
Object keysAny double-quoted string, including empty "".Unquoted identifiers and single-quoted names.API field names — the quotes are not optional.
NumbersDecimal integers and fractions with optional exponent and leading minus: -12, 3.5, 2e10.Hex (0x1F), leading zeros (01), a leading plus (+5), NaN, Infinity.Counts and measures; keep 64-bit IDs as strings.
CommasSeparators between members and between elements.A trailing comma after the last item.Machine-generated payloads and diffs.
CommentsNothing — the grammar defines no comment token.// line comments and /* block */ comments.Interchange only; keep notes in a sibling field.
Top-level valueAny single JSON value — object, array, string, number, boolean, null.Two consecutive values or a truncated document.One document per file or per response body.
JSON5
Unquoted keysBare ECMAScript identifier names as object keys.Keys with spaces, dashes, or a leading digit — those still need quotes.Hand-edited config that reads like source (package.json5).
Single quotesSingle- or double-quoted strings, escaped line breaks, backslash line continuations.Raw unescaped line terminators inside a string.Config you type by hand.
Comments// line comments and /* block */ comments.Nested block comments — the first */ closes the whole comment.Annotating intent in long config files.
Trailing commasA comma after the final member or element.Skipping a comma between two values — separators are still required.Lines you add, reorder, and delete often.
Extended numbersHex (0xFF), leading zeros, a leading dot (.5), a plus sign (+5), Infinity, NaN.Round-trips through strict JSON.parse — each of these is a syntax error.Local config only; convert to JSON before shipping.
JSONC
JSONCStrict JSON plus // and /* */ comments.The other JSON5 extensions — unquoted keys and single quotes stay errors.VS Code settings.json, tsconfig.json, and other tool config.
tsconfig.jsonComments and trailing commas, accepted by the TypeScript compiler.Values that are not strict JSON.Compiler options in every TypeScript project.
VS Code settingsComments; the editor's parser also tolerates trailing commas.Unquoted keys — flagged as invalid.Per-user and workspace editor settings.
Round-tripStrip the comments, then reuse the file as data.Feeding raw JSONC to JSON.parse.Config that is both human doc and machine input.
JSONL / NDJSON
JSON LinesOne complete JSON value per line, newline-separated; readers ignore empty lines.An enclosing array, or one value pretty-printed across lines.Streaming logs and event exports.
StreamingParse each line as it arrives; memory stays flat.Random access to record N without scanning the file.Tail-and-follow pipelines and HTTP streaming bodies.
jq -cjq -c emits each value on one line.Piping default pretty-printed jq output onward — it breaks the framing.Turning pretty JSON into JSONL.
Media typeapplication/x-ndjson; .jsonl and .ndjson file names.application/json — it says nothing about line framing.NDJSON HTTP responses and file exports.
Text toolsLine-oriented tools: grep, tail -f, wc -l, awk.Whole-document tools until you join the lines back.Shell-first debugging of big exports.
Quirks
Big integersExact integers up to 2^53 − 1 (9007199254740991) in JavaScript.Precision beyond that — JSON.parse reads 9007199254740993 as 9007199254740992.Serialize 64-bit and Snowflake IDs as strings.
Duplicate keysParsers accept them, and most keep the last value.Nothing enforces uniqueness — the RFC only says names SHOULD be unique.Generate strictly; lint with a duplicate-key checker.
\u escapesSurrogate pairs for astral characters — 😀 is \ud83d\ude00; raw UTF-8 elsewhere.Unescaped control characters; lone surrogates are ill-formed Unicode.Transports that mangle non-ASCII bytes.
NaN / Infinitynull as the sanctioned stand-in.The literals — JSON.stringify(NaN) emits null and JSON.parse rejects the words.Numeric APIs that must not emit invalid JSON.
undefinedJSON.stringify silently drops undefined object properties.Round-tripping undefined — array slots become null and object keys vanish.Expect missing keys, not undefined, after a serialize cycle.
Key orderInsertion order in JavaScript, with integer-like keys sorted first.Relying on order — the spec does not guarantee it and serializers reorder.Sort keys explicitly when output must be deterministic.