JSON Formatter
Validates a complete UTF-8 JSON document and rewrites only the whitespace that JSON defines as insignificant. Readable and minified output preserve key order, duplicate names, string escapes and every original number token.
A UTF-8 JSON document up to 25 MB. Its bytes stay in this browser tab.
Results are provided as-is, with no warranty of accuracy. The method and its sources are published below so you can check the working.
How it works
What this works out
JSON looks simple until a formatter changes data that was never supposed to be
interpreted. The common shortcut is JSON.stringify(JSON.parse(file)). That
produces tidy output, but it also passes every number through JavaScript’s
binary64 Number, collapses duplicate object names to one value, and chooses
new escape and exponent spellings.
This tool separates validation from rewriting. The browser’s JSON parser proves that the complete source is a conforming value. A second, deliberately smaller scanner copies the original tokens and changes only the whitespace RFC 8259 calls insignificant.
The method
RFC 8259 defines a JSON text as whitespace, one value, then whitespace. A value
can be an object, array, number, string, true, false or null. The only
whitespace characters in the grammar are space, tab, line feed and carriage
return, and they are permitted around six structural characters:
[ ] { } : ,
That gives the formatter a narrow edit surface. Outside a quoted string those four whitespace characters can be removed. Inside a string, a space is data, and a backslash determines whether the next quotation mark ends the string or is part of it. The scanner therefore keeps two bits of state: inside a string and the previous character was an escape.
Readable mode inserts a newline and indentation after a non-empty {, [, or
comma, a single space after a colon, and a newline before a non-empty closing
container. Minified mode inserts nothing. Neither mode converts a primitive
token into a language value.
Before you read on
Which formatter is safe for the JSON number 9007199254740993?
Validate the document, then carry the original number token into the output. RFC 8259 permits implementations to limit numeric precision and identifies the interoperable exact-integer range around 2^53; a whitespace formatter does not need to spend that precision at all.
A worked example
The one-line source is:
{"invoice":9007199254740993,"notes":"keep two spaces","items":[true,null]}
With Readable and 2 spaces, the downloaded file is exactly:
{
"invoice": 9007199254740993,
"notes": "keep two spaces",
"items": [
true,
null
]
}
The two spaces inside "keep two spaces" remain data. The large invoice
number keeps its original digits. The deepest nesting is 2: the root object is
level 1 and its array is level 2. The formula test asserts the complete output
bytes, filename, MIME, byte counts and depth shown by the result panel.
Why number text and object order remain untouched
RFC 8259 permits number magnitudes and precision beyond what binary64 can hold,
while noting that integers from -(2^53)+1 through (2^53)-1 are the range
implementations commonly agree on exactly. A formatter that parses
9007199254740993 into binary64 may write 9007199254740992. Removing a line
break never required that conversion, so this tool does not do it.
The RFC also says object names should be unique, then documents what happens when they are not: some parsers keep the last value, some fail, and some expose all duplicates. It similarly notes that libraries differ over whether member order is visible. Sorting or deduplicating may be useful in a specialised data cleanup workflow, but neither is honest under a button labelled Format.
What it does not do
It does not repair invalid JSON, quote bare object names, remove comments, accept trailing commas, sort keys, or convert JSON5. Those operations need a policy for ambiguous input. Here malformed input is reported and the original file remains untouched.
It also does not change character encoding. Interoperable JSON is UTF-8, and an initial UTF-8 BOM is accepted only because RFC 8259 allows parsers to ignore one for compatibility. To recover known UTF-16 plain text, convert the bytes first; do not ask a JSON formatter to guess what characters they meant.
How it is done
- Read the file as strict UTF-8. Accept and consume an initial UTF-8 byte-order mark for compatibility, but do not write one into the result.
- Validate the complete document as one RFC 8259 JSON value before producing an artifact. Refuse an empty file, invalid UTF-8, trailing content or malformed objects, arrays, strings, numbers and literal names.
- Scan the validated source while tracking quoted strings and backslash escapes. Inside a string, copy every code unit exactly; outside a string, discard only space, tab, carriage return and line feed.
- For readable output, insert the selected indentation after an opening container and comma, one space after a colon, and a correctly indented line before a non-empty closing container. For minified output, insert no optional whitespace.
- Encode the rewritten text as UTF-8, add one final line feed only when selected, and offer a new .json file. Never parse number tokens into floating-point values for output.
What it assumes
- Formatting is not canonicalisation. Object member order, duplicate names, number spelling and string escape choices stay as authored even where another parser might normalise or collapse them.
- JSON exchanged between independent systems is UTF-8 under RFC 8259. UTF-16 and legacy code pages belong in the separate text-encoding converter before this grammar is applied.
- The native JSON parser is used as a strict grammar validator only. The downloadable bytes come from a token-preserving scan of the original text, not from JSON.stringify.
- Input is capped at 25 MB. The rewrite yields every 250,000 characters so progress and Cancel remain responsive; native validation itself is intentionally left to the browser's optimised parser.
Common questions
Does the JSON file leave this device while it is formatted?
No. Strict decoding, grammar validation, whitespace rewriting and file creation happen inside a worker in this browser tab. The generated browser test supplies a real JSON file and fails if tool use sends an off-origin request.
Can formatting round an integer larger than JavaScript can represent exactly?
Not here. The validator may inspect the grammar, but the writer copies the original number characters rather than serialising a JavaScript Number. An integer such as 9007199254740993 therefore keeps every digit.
Are duplicate object names removed?
No. RFC 8259 recommends unique names for interoperability but describes inconsistent parser behaviour when duplicates exist. This formatter preserves every member in its original order so formatting does not make that product decision silently.
Does minifying remove spaces or line breaks inside a string?
No. A quoted string is copied byte-for-byte after UTF-8 decoding, including ordinary spaces and escaped control characters. Only the four JSON whitespace characters found outside a string are optional.
Will the formatter sort keys or make canonical JSON?
No. Sorting changes member order and canonicalisation also changes token spelling. This tool has one narrow promise: validate the document and change insignificant whitespace only.