Skip to main content
UtilitiesFree · no sign-up

JSON Formatter and Validator

Pretty-print, minify or browse JSON as a collapsible tree, with the parse error pointed at the line that broke it.

Updated

Parsing and formatting happen in your browser. Nothing is uploaded, stored, or written into the page URL, which matters when the payload is a real API response.

Formatted

{
  "tool": "json-formatter",
  "runsInBrowser": true,
  "limits": {
    "upload": null,
    "depth": {
      "reported": true,
      "counted": "arrays and objects"
    }
  },
  "tags": [
    "format",
    "minify",
    "validate"
  ]
}

Tree

{ 4 keys }
tool: "json-formatter"
runsInBrowser: true
limits: { 2 keys }
upload: null
depth: { 2 keys }
reported: true
counted: "arrays and objects"
tags: [ 3 items ]
0: "format"
1: "minify"
2: "validate"
Nesting depth
3
Keys
8
Objects and arrays
3 and 1
Minified size
166 B
Minifying saves
nothing, it is already minified

JSON has no comments and no trailing commas, and duplicate keys are not an error: the last one silently wins. If a payload only parses in your editor, one of those three is usually why.

Advertisement

In short

Why does my JSON say invalid when it looks fine?

Almost always one of three things JSON forbids and JavaScript allows: a comment, a trailing comma, or a string in single quotes. None of the three is legal JSON. This page gives you the line and column rather than a bare verdict, so the trailing comma in its own broken sample is reported at line 3, column 25.

Two more silent traps: duplicate keys are legal and the last one quietly wins, and any integer above 9,007,199,254,740,991 loses precision the moment it is parsed.

How to use the JSON formatter and validator

Paste on the left and the formatted document appears on the right, updated on every keystroke. Under it the same document is drawn as a collapsible tree, so a payload too long to scroll can be opened branch by branch. The panel then reports the nesting depth, the number of keys, how many objects and arrays there are, the minified size, and the bytes minifying would save.

Depth is the figure people underestimate. A response that reads as flat often nests four or five levels once you count every wrapper object, and deep nesting is what makes a payload hard to consume. Each array or object opens one more level, while a string, a number, a boolean and null open none.

30.0%

Saved by minifying

the sample at 2 spaces, 237 to 166 bytes

41.8%

Saved at 4 spaces

285 bytes down to 166

22.1%

Saved with tabs

213 bytes down to 166

Advertisement

Those three figures are the same document formatted three ways, and they answer a common argument. Pretty printing is not free, but the cost is whitespace and whitespace compresses to almost nothing. Once the response is gzipped or Brotli compressed the difference between the four versions is close to noise.

Sorting keys is the underrated switch. JSON objects have no defined order, so two servers can send the same data in different sequences and produce a diff full of moved lines. Sorting recursively before comparing collapses that noise, and it makes a payload easier to scan when you are looking for a field by name.

Nothing you paste leaves your browser. Parsing, formatting and measuring all happen on this page, with no upload, no logging, and nothing written into the page URL. Real API responses carry real customer data, and this tool is built so that pasting one here does not become a disclosure.

Do

  • Read the line and column before rereading the whole document.
  • Sort keys on both payloads before diffing two API responses.
  • Ask the API to send identifiers above 2^53 as strings.
  • Minify for the wire and pretty print for the file in your repository.
  • Match the indent your linter already enforces, whichever one that is.

Don't

  • Put comments in a file that a strict JSON parser has to read.
  • Assume a duplicate key is an error, because it parses and the last wins.
  • Trust that a very large identifier survived the round trip unchanged.
  • Paste a production response containing customer data into an online validator.
  • Count on trailing commas because your editor and your bundler tolerate them.

The mistakes that stop a JSON document parsing, what the parser calls each one, and the fix.

What you wroteLegal JSON?What the parser calls itThe fix
A // or /* */ commentNoExpected property name or '}'Remove it, or use JSONC if the reader supports it
Trailing comma in an objectNoExpected double-quoted property nameDelete the last comma
Trailing comma in an arrayNoUnexpected token ']'Delete the last comma
Single-quoted stringNoExpected property name or '}'Use double quotes everywhere
Unquoted key {a: 1}NoExpected property name or '}'Quote every key
NaN or InfinityNoUnexpected token 'N' or 'I'Send null, or a string, and decide at the receiver
Leading zero, as in 01NoUnexpected numberWrite 1, or quote it if it is a code
.5 or 5. as a numberNoUnterminated fractional numberWrite 0.5 and 5.0
A raw newline inside a stringNoBad control character in string literalEscape it as backslash n
Duplicate keysYesnothing at all, it parsesNothing to fix, but the last value silently wins
Integer above 2^53 − 1Yesnothing at all, it parsesHave the API send it as a string
The wording in the third column comes from the browser own JSON parser and varies a little between browser versions. The line and column this page reports are computed here and do not vary.

What JSON forbids that JavaScript allows

JSON started as a subset of JavaScript and stayed small on purpose. The grammar fits on one page, which is why there is a parser for it in every language. Everything convenient that JavaScript added afterwards, and everything a developer reaches for out of habit, is outside that grammar.

JSON is a lightweight, text-based, language-independent syntax for defining data interchange formats.
ECMA-404, The JSON Data Interchange Syntax, 2nd edition, December 2017
  • No comments of either kind, which is the most common complaint about the format.
  • No trailing comma after the last element of an array or the last member of an object.
  • Strings use double quotes only, and every key must be quoted.
  • No NaN, no Infinity, no undefined, and no leading zero on a number.
  • A number needs a digit on both sides of the point, so .5 and 5. are both invalid.

The formats that relax those rules are real but separate. JSONC adds comments and is what editors use for configuration files. JSON5 adds comments, trailing commas, unquoted keys, single-quoted strings and hexadecimal numbers. Neither is JSON, and a strict parser at the other end of an API will reject both without apology.

The practical rule is to know which one you are writing. A configuration file your own tooling reads can be JSONC. Anything crossing a network boundary should be plain JSON, because you do not control the parser on the other side and the tolerant behaviour you are relying on is not in the specification.

The two failures that do not raise an error

A syntax error is the easy case, because something tells you. The two problems worth learning are the ones where the parser succeeds, hands you a value, and never mentions that the value is not what the sender wrote.

What the parser does without telling you
Duplicate key {"a":1,"a":2}
parses, and the result is {"a":2}
What the specification says
behaviour is not defined, so parsers differ
Integer 9007199254740993
parses as 9007199254740992
Safe whole number ceiling
9,007,199,254,740,991, which is 2^53 − 1

Both are legal documents. Neither raises an error anywhere. The duplicate key count on this page collapses along with the parser, so a key count lower than you expected is itself a hint that duplicates were present.

Duplicate keys matter most where documents are merged or generated by templating, because that is where the same key gets emitted twice without anyone intending it. RFC 8259 calls the behaviour undefined and warns that implementations differ, so a payload that works against one server can behave differently against another.

The number problem is bigger and more common. Database identifiers, snowflake IDs and timestamps in nanoseconds all routinely exceed 2^53 − 1, and every one of them loses its last digits in a JavaScript parser. The only real fix is at the source: send the value as a string and parse it deliberately.

Carrying binary through a JSON field

JSON has no byte type, so a file or a key inside a payload has to travel as text. Base64 is the usual answer, and the size cost is worth checking first.

Open the Base64 encoder

Advertisement

The formula, worked line by line

There is no arithmetic in formatting, only counting, so the definitions matter more than any calculation. Depth, keys and size are the three figures this page reports, and each of them is defined below exactly as the tool computes it rather than as a rule of thumb.

The error location is the one genuine computation. A parser reports a character offset into the document, which is useless to a person reading 400 lines. Turning that offset into a line and a column is a matter of counting the newlines before it, and that is the whole trick.

depth = deepest nesting of arrays and objects, a plain value is 0
keys = every object key at every level, after duplicates collapse
bytes saved = input bytes − minified bytes
error line = 1 + the number of newlines before the offending character
error column = offset − start of that line + 1
Nesting depth in a JSON documentThe sample document nests 3 levels deep: the document itself, the limits object inside it, and the depth object inside that. It holds 8 keys across 3 objects and 1 array. Pretty printed at 2 spaces it is 237 bytes and minified 166, so minifying strips 30 percent of it back off.DEPTH 3 · 8 KEYSthe document4 keys"limits"2 keys"limits" then "depth"2 keys123every array or object opens one more level; a string or number opens noneTHE SAMPLEpretty printed237 Bminified166 Bobjects and arrays3 + 1minifying saves30%
The sample document nested three levels deep, with its key count and the bytes minifying removes.
The sample document, four ways
Minified
166 bytes
Indented with a tab
213 bytes, 22.1 percent larger
Indented with 2 spaces
237 bytes, 30.0 percent larger
Indented with 4 spaces
285 bytes, 41.8 percent larger
Depth and keys
3 levels, 8 keys

The same 8 keys across 3 objects and 1 array. All four versions parse to exactly the same value, which is the point: indentation is for the reader and carries no meaning at all.

Depth counts containers, not values. A single number is depth 0, an empty object is depth 1, and an object holding an object holding an object is depth 3. That last one is the sample above, whose limits object contains a depth object, and it is why the figure is a useful proxy for how awkward a payload will be to consume.

Byte counts here are UTF-8 bytes rather than characters, because that is what a network and a size limit actually measure. A document full of non-Latin text is larger than its character count suggests, and an emoji in a string is four bytes even though it looks like one character on screen.

Minification saves whitespace and nothing else, so its value depends entirely on whether the response is compressed. Over a gzipped or Brotli connection the saving shrinks to very little, because repeated runs of spaces are exactly what a compressor removes best. Uncompressed, in a log line or an embedded string, the figures above are the real ones.

Advertisement

Questions people ask

Why can I not put comments in JSON?

Because the grammar has no rule for them. Douglas Crockford removed comments from the format deliberately, on the grounds that people were using them to carry parsing directives and breaking interoperability. The result is that both // and the slash star form are syntax errors in every strict parser, and this page will point at the first slash. If you need comments in a configuration file, use JSONC, which most editors read, or JSON5. If the file crosses a network boundary, keep it plain and put the explanation in a documented field or somewhere else entirely.

Covered in depth in Putting JSON in a URL: Validate, Minify, Percent-Encode, or Base64url?

Are duplicate keys an error in JSON?

No, and that is exactly what makes them dangerous. A document such as the one with an a key set to 1 and then to 2 parses without complaint, and JavaScript hands you the last value, so the 1 disappears. RFC 8259 says the behaviour of a parser receiving duplicate names is unpredictable and that implementations differ, so another language might give you the first value or an error instead. Because the winning key collapses before this page counts anything, a key count lower than you expected is often the first sign that duplicates are present.

Why did my large ID number change after parsing?

Because JavaScript numbers are IEEE 754 doubles, which represent whole numbers exactly only up to 9,007,199,254,740,991, that is 2 to the power 53 minus 1. Anything larger is rounded to the nearest representable value the instant it is parsed: 9007199254740993 becomes 9007199254740992. JSON itself sets no limit on number size, so the document is perfectly valid and nothing raises an error. This page counts such values and warns you, but the original digits are already gone. The only real fix is for the sender to emit large identifiers as strings.

Does minifying JSON actually make a difference?

It depends on whether the payload is compressed. The sample document on this page is 166 bytes minified and 237 bytes at two-space indentation, so minifying removes 30 percent, rising to 41.8 percent against four-space indentation. Those are real savings for anything uncompressed, such as a value stored in a database column, embedded in a log line or held in a size-capped message. Over a gzipped or Brotli connection the gap narrows sharply, because runs of repeated spaces are the easiest thing in the world for a compressor to remove.

Is my JSON uploaded anywhere when I paste it here?

No. Parsing, formatting, sorting and measuring all run in your browser on this page. Nothing is sent to a server, nothing is logged, nothing is stored between visits, and the document is never written into the page URL, so there is no shareable link quietly carrying it around. That matters because the thing people most often paste into a JSON formatter is a real API response, which usually contains real customer records, real tokens, or both. Close the tab and it is gone.

Sources

Where the constants and formulas on this page come from. Each line names the figure it backs.

  1. Behaviour is unpredictable when object names are not unique, and integers outside plus or minus 2 to the 53rd are not interoperable across implementations.

    RFC 8259: The JavaScript Object Notation (JSON) Data Interchange FormatIETF, 2017

  2. The JSON syntax itself, defined independently of any programming language.

    ECMA-404: The JSON data interchange syntax, 2nd editionEcma International, 2017