JSON (JavaScript Object Notation) is the data format that ate the world - originally specified by Douglas Crockford in 2001 and now described by RFC 8259 / ECMA-404. It is the wire format for almost every REST API, the on-disk format for package.json, tsconfig.json, .vscode/settings.json, and a thousand other config files. A formatter takes a compact or malformed-looking JSON document and re-emits it with consistent indentation so a human can actually read it.
This formatter is a thin wrapper around two native JavaScript built-ins: JSON.parse and JSON.stringify. JSON.parse runs the same parser the V8 engine uses to evaluate fetch().json() responses, so its strictness exactly matches what your runtime accepts. JSON.stringify with the third argument (the spacer) emits the canonical pretty-printed form. There's no third-party library, no WASM blob - just the standards-compliant parser already in your browser.
Validation runs live on every keystroke (with a 350 ms debounce on the auto-format pass). When parsing fails, the JSON.parse error message includes the position of the first bad character ("Unexpected token } in JSON at position 87"). The status strip surfaces that message verbatim, so you can jump to the offending byte and fix the dangling comma or unterminated string. When parsing succeeds, the stats panel walks the parsed tree and reports total keys, depth, array count, and null count - useful for spotting that a deeply nested config has 12 levels of nesting where you expected 3.
The Sort Keys option recursively alphabetizes every object's keys at every level of nesting (sortKeysDeep in the source above). This is the key step before diffing two JSON files, because JSON object keys are unordered by spec - two semantically-equal objects might serialize with different key orders depending on the producer. Sorting both sides first makes a textual diff actually meaningful. It's also the trick behind canonical JSON formats used for hashing and signing.
Indent sizes of 2, 4, or 8 spaces cover the three common conventions: 2 (Airbnb, StandardJS, most modern JavaScript codebases), 4 (Python-derived, older Java configs, legacy .NET appsettings.json), and 8 (rare but useful for very long single-line objects where 2-space indent makes structure hard to follow). Tabs aren't exposed because JSON.stringify accepts them but most consumer tools (jq, jsonlint) prefer spaces.
Minification produces JSON.stringify(parsed) with no spacer - the most compact valid representation. It strips all whitespace including newlines but cannot remove semantically-meaningful characters (the standard requires the commas, colons, brackets, and braces). For 100 MB+ payloads, the savings are around 20-30%; for small API responses, gzip compression on the wire is usually a bigger win. Use minify when you need to embed JSON in a URL, in a meta tag, or as a single-line value in a YAML file.
Two practical limits worth noting. First, JSON has no native support for cyclic references, infinity, NaN, undefined, BigInt, or Date objects - all of which JavaScript can express but JSON.stringify will silently strip or throw on. If your input came from JSON.stringify(myObj) where myObj had a Date, the date became a string. Second, the recursive parse / sort / stringify pipeline holds the full tree in memory; pasting a 200 MB JSON document will stall the tab. For files that big, use jq or pandas on the command line.