JSON has rules. Most JSON in the wild breaks them.
JSON is famously simple — RFC 8259, eight types, the entire grammar fits on one page. In production code, JSON breaks in beautiful ways: trailing commas, single quotes, JavaScript-style comments, NaN and Infinity, integers larger than 253, dates pretending to be strings. The beautifier on this page is strict on purpose. Here is what a strict parser refuses, what it has to accept, and the dialects that explain why your file might not parse.
Strict JSON (RFC 8259) — what the spec actually requires
Object keys must be double-quoted strings. No trailing commas. No comments. Numbers are decimal, no leading zeros, no hex, no + prefix. Only the literal true, false, null are valid (lowercase). Strings are UTF-8 with double quotes, allowing the listed escapes (\", \\, \/, \b, \f, \n, \r, \t, \uXXXX) and nothing else. That is the whole standard.
JSON5 — the relaxed dialect everyone secretly wants
JSON5 allows trailing commas, single-quoted strings, unquoted object keys (when they are valid JS identifiers), JavaScript-style line comments (//) and block comments (/* */), hexadecimal numbers, leading-decimal numbers (.5), and explicit + sign on numbers. It is widely supported in tooling (Babel, ESLint configs) but is not JSON. If your file fails to parse here, JSON5 is the usual culprit.
JSONC — VS Code’s tsconfig.json dialect
JSONC adds only comments (line and block) to strict JSON. Microsoft introduced it for tsconfig.json and similar config files where developers want to annotate options without breaking the structure. Many tools advertise “JSON” support but actually parse JSONC. If your config file has comments and works in VS Code but not in JSON.parse, that is why.
The 253 integer problem
JSON numbers are spec’d as IEEE 754 double-precision floats. Integers up to 253 − 1 (9 007 199 254 740 991) round-trip safely. Beyond that, precision is lost silently: 9007199254740993 becomes 9007199254740992 after parsing. Twitter learned this in 2011 when their tweet IDs crossed the threshold and JavaScript clients started losing the last digit. The right answer is to serialise large integers as strings ("9007199254740993") or use a parser that supports BigInt (most don’t, by default).
NaN, Infinity, and Python’s default lie
NaN, Infinity, -Infinity are not valid JSON. They cannot be represented. Python’s json.dumps() nevertheless emits them as bare tokens by default (NaN unquoted), producing strings that look like JSON but fail in any strict parser. Pass allow_nan=False to make it throw instead. JavaScript’s JSON.stringify() does the right thing by default — it emits null for NaN and Infinity.
Dates: there is no JSON date type
JSON has no date primitive. Every “date in JSON” you have ever seen is a string, a Unix timestamp number, or a custom object. The de facto standard is ISO 8601 strings ("2026-05-27T14:30:00Z") because they sort lexicographically. Unix timestamps in milliseconds work too but force every consumer to handle timezone display. Either convention is fine; mixing them in one API is not.
Takeaway: The beautifier on this page accepts strict RFC 8259 JSON. If your file fails, it is almost always JSON5 (trailing comma, comment, single quote, unquoted key) or Python-flavoured pseudo-JSON (NaN, Infinity). Either fix the file at the source or switch to a parser that explicitly handles the dialect — silent acceptance of non-spec JSON downstream is a footgun that creates “works on my machine” bug reports for years.
Sources: RFC 8259 (JSON) · JSON5 specification · ECMA-404 (JSON Data Interchange Syntax).