JSON Formatter & Validator
How it works
Why 9007199254740993 comes back as 9007199254740992
JavaScript stores every JSON number as an IEEE 754 double, which has 53 bits of integer precision. Number.MAX_SAFE_INTEGER is 9007199254740991; above it, not every integer exists, so JSON.parse rounds to the nearest representable one — 9007199254740993 becomes 9007199254740992 with no error. This bites real data constantly: 64-bit database ids, Twitter/X snowflake ids, nanosecond timestamps. This tool detects integer literals that cannot round-trip and shows a warning naming the original and the rounded value. The formatted output still contains the rounded number — that is a limit of JSON.parse itself — so the fix upstream is to transmit such ids as strings.
Duplicate keys are legal, silent, and last-wins
RFC 8259 only says object names SHOULD be unique, so {"a":1,"a":2} is syntactically valid JSON. The ECMAScript spec makes JSON.parse keep the last occurrence, so the first value vanishes without any error — a classic source of config files where an edit 'does nothing' because the same key appears again lower down, and of parser-differential security bugs when another system keeps the first value instead. This tool scans for duplicate keys (comparing decoded names, so "a" and "a" count as the same key) and warns which ones were collapsed.
Errors with a real position
A bare 'Unexpected token }' is useless in a 500-line payload. When the input is invalid, this tool reports the line and column of the failure whenever the engine provides a position (Chrome and Edge do for most errors; the raw engine message is shown otherwise) — for example a trailing comma in {"a":1,} is reported at line 1, column 8. Trailing commas and comments are the usual suspects: both are fine in JavaScript object literals, JSON5 and JSONC, but hard errors in JSON.
Sort keys for stable diffs
Two JSON documents with the same data but different key order diff as if everything changed. The Sort keys option recursively sorts every object's keys, so formatting the before and after versions gives a minimal, readable diff. Combined with Minify it also produces a canonical-ish single line for comparing payloads.
Examples
| { "a" : 1 , "b" : [ 2 , 3 ] } | {"a":1,"b":[2,3]} |
| {"id":9007199254740993,"user":"kai"} | {"id":9007199254740992,"user":"kai"} — warns: 9007199254740993 was read as 9007199254740992 |
| {"a":1,"a":2} | {"a":2} — warns: duplicate key "a", JSON.parse keeps only the last value |
| {"b":1,"a":{"d":2,"c":3}} | {"a":{"c":3,"d":2},"b":1} (Sort keys + Minify) |
FAQ
Why did my large number change after formatting?
JavaScript parses every JSON number into a 64-bit float with 53 bits of integer precision. Any integer above Number.MAX_SAFE_INTEGER (9007199254740991) may not be representable, and JSON.parse silently rounds it to the nearest double — 9007199254740993 becomes 9007199254740992. This tool warns when that happens, but the output necessarily contains the rounded value. If you control the producer, send 64-bit ids as JSON strings.
Is JSON with duplicate keys valid?
Syntactically yes: RFC 8259 says object names SHOULD be unique, not MUST. Behavior is parser-defined — JavaScript's JSON.parse keeps the last occurrence, and this tool warns which keys were collapsed. Because other parsers may keep the first occurrence or reject the document, duplicate keys are an interoperability and security hazard and should be removed.
Why is a trailing comma an error?
JSON allows neither trailing commas nor comments; both are features of JavaScript object literals, JSON5 and JSONC (the VS Code settings dialect). {"a":1,} fails with the position reported as line 1, column 8 — delete the comma before the closing brace.
Does formatting change my numbers?
Representation can change, value cannot (except for the unsafe-integer rounding this tool warns about). JSON.parse turns the text 1.0 into the number 1 and 1e2 into 100, so the output shows 1 and 100. One extreme case gets a warning: a literal like 1e999 overflows to Infinity, which JSON.stringify writes as null.
Is my JSON uploaded to a server?
No. The page ships a strict Content-Security-Policy: connect-src 'none' blocks fetch, XHR, WebSockets and beacons, while default-src 'self' and form-action 'none' block every other way markup could send data off-site. Parsing and formatting happen in your browser and cannot leave it.