JSON Formatter & Validator
How to use it
Paste JSON into the box, pick an output style and press Format. You can indent with 2 spaces, 4 spaces or a tab, or minify to a single line. "Sort keys" orders object keys alphabetically at every level, which is handy for diffing two documents. When the input is valid, Copy puts the result on your clipboard and Download saves it as a .json file. When it is not, you get the line, the column and a short excerpt with a caret under the problem.
Everything runs in your browser. The text is never uploaded, and the page makes no network requests while you work.
Why big numbers get corrupted elsewhere
JavaScript's JSON.parse turns every number into an IEEE 754 double, which has 53 bits of integer precision. Integers up to 9,007,199,254,740,991 (2^53 - 1) are safe. Past that, neighbouring integers collapse onto the same double. Try this in a console: JSON.parse("12345678901234567890") gives 12345678901234567000, and 9007199254740993 comes back as 9007199254740992.
This is why 64-bit IDs, such as the numeric IDs used by Twitter-style APIs, are often sent as strings next to the numeric field. Any tool that parses and re-prints through JSON.parse and JSON.stringify will silently change them. The same happens to long decimals: 1.000000000000000000001 becomes 1.
This formatter does not convert numbers at all. It has its own parser that stores each number as the exact text you typed and writes that text back out unchanged, so 12345678901234567890 stays 12345678901234567890 in every output style. It also warns you about each number that a normal JSON.parse would have rounded, with its path, for example $.user.id. An integer is flagged only when its double really differs from it (9,007,199,254,740,992 is exact, 9,007,199,254,740,993 is not), and so are decimals or exponent forms whose value changes when converted to a double. A warning is not an error: the document is still valid, and your digits are intact in the output.
What the validator checks
The parser follows RFC 8259 strictly and does not try to be forgiving. It rejects:
- Trailing commas, such as
[1, 2,]or{"a": 1,}. - Comments, both
// lineand/* block */. - Single-quoted strings and unquoted keys.
- Numbers with leading zeros (
01), a leading plus (+1), a leading or trailing dot (.5,1.), and the non-JSON valuesNaNandInfinity. - Raw control characters inside strings (a literal tab or newline), and invalid escapes such as
\qor a\uescape without four hex digits. - Any text after the top-level value, and empty input.
Only the first error is reported, for example "Trailing comma is not allowed (line 1, column 8)". A leading byte order mark is ignored. Duplicate keys in one object are allowed by the RFC, though its authors warn that behaviour then varies between parsers, so you get a warning with the path, such as $.a.b, and every occurrence is kept in the output.
Limitations
- Strings are decoded and written back, so equivalent escapes are normalised:
écomes out as the character itself and\/as/. The meaning is identical, but the bytes of the text can differ. Lone surrogate escapes such as\ud83dare kept escaped. - The output keeps your numbers as written, so
1.50stays1.50and1E5stays1E5. - Sorting compares keys by UTF-16 code unit, not by locale.
- Pretty-printing extremely deep nesting needs output that grows with the square of the depth, so past a point the tool falls back to minified output and says so. Parsing itself handles tens of thousands of levels, and inputs of several megabytes work, though a very large document takes a moment and fills the result box with a lot of text.
- The tool checks syntax only. It does not validate against a JSON Schema, and it cannot repair broken JSON.
Last reviewed: