JSON Formatter
Expected result: Expand orders to inspect two items; paid is false and total is 42.5. Copy returns JSON with two-space indentation.
Limitations: Uses JavaScript JSON parsing: duplicate keys collapse and large integers can lose precision. Quote identifiers that must remain exact.
Nothing you enter here is stored, logged or shared.
Paste JSON to indent it readably and check that it parses, with the line and column of any error and a collapsible tree for finding your way around an unfamiliar response.
How to use
- Paste your JSON into the input field.
- The formatted result appears immediately.
- Copy the result with the copy button.
What this formatter accepts
The parser follows RFC 8259 exactly, which is stricter than most people expect. Keys must be double-quoted. Strings must use double quotes, never single. There is no trailing comma after the last element of an object or array, no comment syntax of any kind, and no NaN, Infinity or undefined. Numbers cannot be written in hexadecimal, cannot carry a leading plus, and cannot have a leading zero on the integer part.
That strictness is deliberate rather than pedantic: it is what every JSON parser on the receiving end will apply. A document that formats here will parse in Python, Go, Rust and PostgreSQL. A document that only works after a lenient parser guesses at your intent will fail somewhere later, usually in production.
If your input has comments or trailing commas, it is not JSON but JSON5 or JSONC, the relaxed variants used by config files such as tsconfig.json. Those are real formats with real uses, and stripping the comments to make the document valid JSON is a lossy edit. Do it knowingly.
Reading the error
When parsing fails the error carries a line and column, derived from the character offset the engine reports. Note that the position is where the parser gave up, not always where you made the mistake: a missing closing brace is usually reported at the end of the document, because everything up to that point was still potentially valid.
The four causes that account for almost every failure are a trailing comma before a closing bracket, single quotes around a string or a key, an unquoted key copied out of a JavaScript object literal, and an unescaped double quote or newline inside a string value. If the reported column points at a quote character, the string before it probably ended early.
Truncated documents are the other common case. A response cut off by a size limit or a timeout parses cleanly until it stops mid-value, so the error lands on the last line rather than anywhere informative. Check the end of the input before hunting through the middle.
What a round trip changes
Formatting parses your document and serialises it again, so a few things are normalised on the way through, and it is worth knowing which.
Numbers become IEEE 754 doubles. Any integer larger than 9,007,199,254,740,991 loses precision, which matters because 64-bit database IDs, Twitter-style snowflake IDs and nanosecond timestamps all live above that line. An ID of 9223372036854775807 comes back as 9223372036854776000. If you need those intact, keep them as strings in the payload. Trailing zeros also go: 1.0 formats as 1, and 1e3 as 1000.
Duplicate keys collapse, last one winning, because the parse step builds an object. Key order is otherwise preserved, with one exception inherited from JavaScript objects: keys that look like non-negative integers sort numerically and move ahead of the rest. Comments and original whitespace are gone by definition, since neither survives parsing.
The tree view
Above the formatted text there is a collapsible tree. It is for a different job: finding the shape of an unfamiliar response, where the interesting field lives, and how deeply it is nested, without scrolling through several thousand indented lines. Collapse the arrays you do not care about and the structure becomes readable in a screen.
The formatted text stays the thing the copy button hands over, so exploring in the tree never changes what you paste back into your editor.
Where JSON came from, and what it can hold
JSON was specified by Douglas Crockford in the early 2000s as a subset of JavaScript's object literal syntax, on the observation that browsers could already parse it and that XML was heavier than most web APIs needed. It was standardised as RFC 4627, later superseded by RFC 8259 and ECMA-404, and the fact that the grammar fits on one page is most of the reason it took over.
The data model is deliberately small: objects, arrays, strings, numbers, booleans and null. That is all. There is no date type, no binary type, no integer-versus-float distinction, no comments, and no way to express a reference from one part of a document to another.
Everything awkward about JSON follows from that list. Dates have to be a convention rather than a type, binary has to be encoded as text, large integers strain a format whose numbers are usually parsed as doubles, and configuration files - which want comments - have to use a dialect or a different format entirely.
Dates, money and big numbers
For dates, the settled convention is ISO 8601 in UTC, as in 2026-03-14T09:30:00Z. It sorts lexicographically, it is unambiguous, and every language can parse it. The alternatives cause trouble: a Unix timestamp loses the distinction between seconds and milliseconds, and a localised string like 03/14/2026 is ambiguous outside the country that wrote it.
Money should not be a JSON number. Parsers are free to use double-precision floats, so 0.1 plus 0.2 problems arrive with the payload, and rounding behaviour differs between languages. Integer minor units - 1999 for £19.99 - with the currency in a separate field is the representation that survives every consumer.
Large identifiers have the same issue in a sharper form. Anything above 2^53 loses precision when parsed into a double, which covers 64-bit database ids and snowflake identifiers, so they belong in the payload as strings. This is not a hypothetical: it is why several large APIs return both an id and an id_str field.
Files too big to hold in memory
A parser that builds the whole document as an object needs several times the file size in memory, so a 500 MB export can exhaust a process on a machine with gigabytes free. Two approaches avoid that.
The first is newline-delimited JSON, where each line is a complete document and the file as a whole is not valid JSON. It streams naturally, appends cheaply, and is what most log pipelines and bulk export formats use. The second is a streaming parser - ijson in Python, a SAX-style reader elsewhere - which emits events as it walks the file and never materialises the whole tree.
On the command line, jq handles both and is worth learning for its own sake: jq '.items[] | {id, name}' big.json extracts a projection without loading the document into an editor. Its --stream flag covers the cases where even jq's default mode would use too much memory.
The security surface of a JSON payload
JSON parsing itself is safe in any modern language; the risks live in what happens next. Prototype pollution is the best known: in JavaScript, merging attacker-controlled JSON into an object without filtering can set __proto__ and change the behaviour of every object in the process. Deep-merge utilities have shipped this bug repeatedly, and the defence is to reject those keys explicitly or use a null-prototype object.
Never evaluate JSON. Using eval to parse it was a real practice in the era before JSON.parse existed, and it executes whatever arrives. Anything that reaches for eval on data today is a finding rather than a style preference.
Two smaller ones are worth knowing. Serving a JSON array with a content type a browser will execute was the basis of old JSON hijacking attacks, which is why some APIs still prefix responses with a loop-breaking line. And duplicate keys are legal in the grammar but handled differently by different parsers, which has been used to smuggle a different value past a validator than the one the application eventually reads.
The dialects, and when to use one
JSON5 adds comments, trailing commas, unquoted keys and single-quoted strings. JSONC is the smaller variant Visual Studio Code uses for its settings and tsconfig.json - essentially JSON plus comments. Neither is JSON, and neither will parse in a standard library without a dedicated package.
The distinction that matters is the audience. A file a human maintains benefits enormously from comments, so JSON5, JSONC, YAML or TOML are all reasonable there. A payload crossing a network should be plain JSON, because the receiving end may be any language and any library version, and a dialect converts an interoperability guarantee into a dependency.
When you paste a configuration file into a strict parser and it fails, that usually means the file is a dialect rather than malformed. Stripping the comments to satisfy the parser is a lossy edit to somebody's documentation, so do it on a copy.
Frequently asked questions
- Is my JSON data uploaded to a server?
- No, and you can check rather than take it on trust: open your browser developer tools, watch the Network tab, and paste. Nothing is requested. That is the reason this page is usable with a production payload or an API response that still has an access token in it.
- What is the maximum size I can format?
- There is no configured limit. The ceiling is your browser memory, and since parsing builds the whole document as objects before serialising it again, expect to need several times the file size in RAM. Documents of a few megabytes are unremarkable; a hundred-megabyte log export is not what this tool is for, and a streaming parser such as jq is the better answer there.
- Why does my JSON show an error?
- The error gives the line and column where the parser stopped. In order of frequency the cause is a trailing comma before a closing bracket, single quotes where JSON requires double, a key left unquoted after copying a JavaScript object literal, or an unescaped quote inside a string value. If the document simply ends mid-value, it was truncated in transit rather than written wrongly.
- Why did my long ID number change?
- Because JSON numbers are parsed as IEEE 754 doubles, which hold integers exactly only up to 9,007,199,254,740,991. A 64-bit database ID or a snowflake ID sits above that, so 9223372036854775807 comes back as 9223372036854776000. This is not a quirk of this page - every JavaScript client that consumes the API has the same problem. The fix is to send such IDs as strings.
- Can it handle comments or trailing commas?
- No, because JSON has neither. A file that uses them is JSON5 or JSONC, the relaxed variants that config files such as tsconfig.json are written in. They are valid formats, just not this one, and stripping the comments to make a document parse is a lossy edit worth making deliberately.
- Are keys reordered or deduplicated?
- Order is preserved, with one inherited exception: keys that look like non-negative integers sort numerically and move ahead of the others, because that is how JavaScript objects behave. Duplicate keys collapse to the last occurrence, which is worth knowing if you are formatting a document specifically to find out whether it has any.
Last updated:
References
RFC 8259 — JSONRecent changes
- — Added a runnable example, expected results, limitations, and reference links.
Include the steps, expected result, and actual result. Remove secrets and personal data.
