JSON Formatter
Paste JSON to pretty-print it, minify it, or find out exactly what is wrong with it. When it parses, two extra checks run that a normal parser will not tell you about.
Duplicate keys found
Duplicate keys are legal JSON, and every parser silently keeps only the last one. If you edited a value and nothing changed, this is usually why. The entries below are paths, not bare key names: x.a means key “a” inside the object at key “x”, and items[0].a means key “a” inside the first element of the array “items”.
Integers too large to represent exactly
JavaScript stores numbers as 64-bit floats, so integers beyond 2^53 − 1 lose precision when parsed. These values will not survive a round trip through this tool or through any JavaScript program. If they are identifiers, store them as strings at the source.
Paste something to get started, or load the example to see what the checks do.
How to use it
Paste your JSON
Validation runs as you type, so a broken paste is flagged immediately rather than after you press a button. Loading the example shows what the two extra checks look for.
Fix anything it complains about
A syntax error is reported with a line, a column and a caret showing the exact spot. Duplicate keys and oversized integers do not stop parsing, so they appear as notes below the output instead — read those even when the JSON is valid.
Choose an indent and format
Two spaces, four spaces or a tab. Tick “sort keys” if you want deterministic output — useful when you are diffing two files or comparing a hash. The output appears beside the input so you can check it before copying.
Copy or download
Copy puts the formatted result on your clipboard; download saves it as a .json file. Minify strips all the whitespace if the goal is a smaller payload rather than something readable.
Two problems that parse cleanly and still ruin your data
A validator that only answers “is this valid JSON?” is answering an easier question than the one you have. Both of the following are perfectly valid JSON, both parse without a single warning, and both silently give you something other than what the file says.
The first is duplicate keys. `{"port": 3000, "port": 8080}` is legal. Every parser, in every language, keeps the last one and forgets the rest without comment. The practical shape of this bug is someone editing a config file, changing the value, saving, restarting, and finding the old behaviour still in place — because the file contains a second, later, identical-looking key that overrides the edit. It is invisible to a syntax highlighter, invisible to a validator, and it costs people whole afternoons.
The second is integers beyond 2^53 − 1, which is 9007199254740991. JavaScript stores all numbers as 64-bit floating point, so integers larger than that cannot be represented exactly. Paste an ID like 9007199254740993 and the parser hands you 9007199254740992. No error, no warning, and the number still looks plausible — it is wrong only in the last digit, which is precisely the kind of wrong that survives review. Database bigints, order numbers and the snowflake IDs used by several large platforms all live in this range.
The damage is one-way. Once the value has been parsed into an imprecise float, serialising it back out writes the rounded number, so a read-modify-write cycle permanently corrupts the original. There is no way to recover it from the parsed value — only from the original text, which is why this tool reads the raw source for these checks instead of inspecting the parsed object.
Why this tool warns instead of fixing it for you
The obvious “helpful” move would be to convert those oversized integers into strings automatically, since a quoted `"9007199254740993"` survives intact. We deliberately do not.
Doing so would silently change the type of your data. A consumer expecting a number would receive a string, comparisons and arithmetic would behave differently, and a schema validation downstream would fail — or worse, quietly coerce. That is the same category of mistake as the one being fixed: a silent change to your data that the syntax looks fine with. A tool that quietly rewrites your values is not safer than one that quietly rounds them.
So the report names the offending literals, shows what each one became when parsed, and leaves the decision with you. The real fix belongs at the source — if a value is an identifier rather than a quantity you do arithmetic on, it should be serialised as a string by whatever produces the JSON. IDs are labels; adding one to another ID is never meaningful. Encoding them as strings from the start removes the entire class of problem for every consumer downstream, not just for this tool.
Where JSON syntax errors actually come from
Most invalid JSON was written by a person who was thinking in JavaScript, and JavaScript is more permissive. The same habits, in rough order of how often they show up:
- Trailing commas. `{"a": 1, "b": 2,}` is fine in JavaScript and forbidden in JSON. This is the single most common cause, and it usually arrives when someone deletes the last item of a list and leaves the comma behind.
- Single quotes around strings or keys. JSON requires double quotes, always, for both.
- Unquoted keys. `{a: 1}` is JavaScript object syntax, not JSON.
- Comments. Neither `//` nor `/* */` is legal in JSON, which is why a config file that works in one tool can fail in another — the tool may be reading JSON5, JSONC or HJSON.
- `NaN`, `Infinity`, `undefined` and hexadecimal numbers. None exist in JSON. Infinity is not representable as a number in JSON at all; the usual convention is `null`.
- A raw newline or tab inside a string literal. JSON forbids literal control characters in strings; they must be escaped as `\n` and `\t`.
Reading the error position correctly
The reported position is where the parser gave up, which is not always where the mistake is. A missing comma between two members is detected when the parser reaches the second member and finds it has nothing to do — so the caret lands on the token after the real problem. When the position looks innocent, look at the line above.
Engine messages also differ. Chrome and Node report a character offset and usually a line and column; Safari’s wording is different again, and Firefox has changed its format over the years. This tool reads whatever the browser reports, and falls back to printing the message unmodified when there is no position in it — some errors genuinely do not have one, and inventing a line number would be worse than admitting that.
The caret display shows the offending line with surrounding context, because a column number alone is hard to act on in a line that is four hundred characters long. If the error has no position at all, the usual suspects are a truncated paste, a byte order mark at the very start (common when pasting from a file saved by a Windows editor), or non-breaking spaces that arrived from a document or a chat message — they look identical to ordinary spaces and are not valid JSON whitespace.
Formatting choices that quietly matter
Indentation is cosmetic for machines and real for people; two spaces is the common convention in JavaScript projects and four in others, and the choice has no effect on how the JSON behaves.
Minifying is where you should be careful. It is the right move for a payload sent over the network, and the wrong move for a file a human will later edit — minified JSON is one enormous line, which makes diffs useless and merge conflicts unresolvable. If the file is going into version control, keep it formatted.
Sorting keys deserves an explicit warning. The JSON specification says object member order is not significant, and for most consumers that is true. But plenty of real systems compare serialised output: a hash or signature computed over a stringified object, a snapshot test, a config file whose checksum is verified. Turn on sorting for those and the output changes, which can invalidate a signature or fail a test even though nothing semantically different happened. Sort to make diffs readable; do not sort something that gets signed.
Last updated:
Frequently asked questions
Is my JSON sent to a server to be validated?
No. Parsing, formatting, minifying and both extra checks run in the page. That matters more here than for some other tools, because JSON pasted into a formatter is frequently a config file with credentials, an API response with tokens in it, or customer data. Nothing is transmitted, stored or logged.
It says the JSON is valid but shows warnings. Which is right?
Both. The JSON is syntactically valid, so it will parse anywhere. The warnings are about what parsing does to your data — a duplicate key that will be dropped, or an integer that cannot be represented exactly. Valid syntax and intact data are different questions.
Why does 9007199254740993 come back as 9007199254740992?
Because JavaScript represents numbers as 64-bit floats, which can hold integers exactly only up to 2^53 − 1, or 9007199254740991. Beyond that the nearest representable value is used, silently. If the value is an identifier, the durable fix is to have the source emit it as a string.
Does formatting change my data?
Formatting and minifying only change whitespace, so the parsed value is identical. Sorting keys is the one exception worth thinking about: the value is unchanged, but the output string is different, which matters if something downstream hashes or signs it.
Can I use this to convert JSON to CSV, YAML or XML?
No — this tool stays with JSON. Format conversion is a different job with different failure modes, particularly around nested structures, which have no natural representation in a flat table.
Why is my JSON with comments rejected?
Because comments are not part of JSON. The `//` and `/* */` forms come from JSON5, JSONC and HJSON — dialects some tools accept. A config file that loads fine in your bundler can be invalid to a strict parser. Strip the comments if the file has to be consumed by something that only speaks JSON.
How large a document can it handle?
There is no fixed limit, and both the parse and the extra checks are linear passes over the text, so a multi-megabyte API response is fine on a modern machine. Very large inputs will make the initial render of the output box take a moment; that is the browser laying out a very long string, not the analysis stalling.