Free JSON formatter and validator. Pretty-print, minify, and validate JSON with syntax highlighting and detailed error messages.
Paste JSON into the left panel and the tool parses it immediately — there is no submit step and nothing is uploaded. If the text parses, the right panel shows it re-indented, a statistics strip appears above with object, array and key counts plus maximum nesting depth and byte size, and the Tree View tab becomes usable. If the text does not parse, the output panel stays empty and the input panel shows the parser's exact error message with the line and column it failed at. That split is the whole point: formatting is a side effect of a successful parse, so a document that refuses to format is a document that is not valid JSON, and the error text tells you where.
Everything runs client-side, so payloads carrying production credentials, customer records or internal hostnames never leave the machine. The optional Auto-Redact toggle goes further and masks values that look like secrets before they are rendered.
Input can arrive by typing, pasting, the clipboard button, uploading a .json file, or dragging a file onto the input panel; Load Sample drops in a small valid document. Output can be copied or downloaded. Small inputs and every option toggle are encoded into the page URL, so the share button produces a link that reopens the same document with the same settings.
These two words get used interchangeably and they are not the same operation. Beautifying answers “what does this document look like with sane whitespace,” and it is a purely cosmetic transform of something that already parsed. Validating answers one of two much harder questions: is this syntactically well-formed JSON, and separately, does it conform to a schema that says which keys are required and what types they hold.
This tool does the first two. It parses, which is syntactic validation, then re-serializes, which is beautification. It does not check the document against a JSON Schema — a payload where "age" is the string "forty" is perfectly valid JSON and formats without complaint. If an API rejects a body that formats cleanly here, the problem is contract-level, not syntax-level.
One consequence: the output is produced by re-serializing the parsed value, not by reflowing your text, so anything the parser normalises away is gone. Comments, trailing commas and the exact spelling of numbers do not survive — a feature when you want a canonical document, a trap when you expected a whitespace-only diff.
Browser engines produce two shapes of message. The better shape names the construct the parser expected and gives an offset plus line and column, for example Expected double-quoted property name in JSON at position 22 (line 4 column 1). The weaker shape appears on a bare token: Unexpected token 'N', "{"score": NaN}" is not valid JSON — no position, just the offending character and a snippet. With the second shape, search for that character rather than counting lines.
The reported position is where the parser gave up, which is frequently one token after the mistake. A trailing comma is the classic case: the comma itself is legal at that point, so the parser only fails when it reaches the closing brace and finds no property name waiting. The error points at the brace on the following line; the fix is on the line before it.
| Input | Parser error | Fix |
|---|---|---|
{"a": 1, "b": 2,} | Expected double-quoted property name in JSON | Delete the comma after the last member. Look one line above the reported position. |
{'name': "Ada"} | Expected property name or '}' in JSON | Single quotes are not JSON. Convert every quote to a double quote. |
{name: "Ada"} | Expected property name or '}' in JSON | Keys must be quoted strings, even when they look like identifiers. |
{ // config | Expected property name or '}' in JSON | JSON has no comments. Strip them, or treat the file as JSONC. |
{"score": NaN} | Unexpected token 'N' … is not valid JSON | Use null. NaN and Infinity have no JSON representation. |
{"a": True} | Unexpected token 'T' … is not valid JSON | Python literal leaked in. JSON booleans are lowercase true / false, and None becomes null. |
{"a": undefined} | Unexpected token 'u' … is not valid JSON | There is no undefined in JSON. Emit null or omit the key. |
{"a": "line1 then a real newline | Bad control character in string literal in JSON | Newlines and tabs inside strings must be escaped as \n and \t. |
{"path": "C:\Users\ada"} | Bad escaped character in JSON | Backslash starts an escape sequence. Double it: C:\\Users\\ada. |
{"a": 0x1F} | Expected ',' or '}' after property value in JSON | No hex literals. Write the decimal value, or quote it as a string. |
{"a": 007} | Unexpected number in JSON | Leading zeros are illegal. Zero-padded identifiers belong in strings anyway. |
{"a": .5} or {"a": +5} | Unexpected token '.' / '+' … is not valid JSON | Numbers need a leading digit and may not carry a leading plus. Write 0.5 and 5. |
{"a": 5.} | Unterminated fractional number in JSON | A decimal point requires at least one digit after it. |
{"a": [1, 2 | Expected ',' or ']' after array element in JSON | Truncated document — usually a response cut off by a timeout or a size limit, not a typo. |
A byte order mark before { | Unexpected token '' … is not valid JSON | Invisible character at offset zero. Re-save the file as UTF-8 without BOM. |
{“a”: 1} with curly quotes | Expected property name or '}' in JSON | Autocorrect damage from a word processor or chat client. Retype the quotes. |
| Two objects on two lines | Unexpected non-whitespace character after JSON | That is NDJSON, not JSON. Parse it a line at a time. |
| Empty input | Unexpected end of JSON input | An empty response body. Check the HTTP status before blaming the parser. |
Duplicate keys are the first. {"a":1,"a":2} is accepted and returns {"a":2} — last value wins, silently. RFC 8259 says names within an object should be unique but does not forbid repeats, and languages resolve them differently: some keep the last, some the first, some raise. If a config behaves as though a setting is ignored, look for the same key twice before anything else. Silent number coercion is the second, covered below.
The grammar is small enough to hold in your head. A JSON text is any single value. Objects are unordered sets of name/value pairs whose names are double-quoted strings; arrays are ordered sequences; the value types are object, array, string, number, true/false and null. Whitespace between tokens is limited to space, tab, line feed and carriage return. Points people get wrong:
42, "hi" and null are each a complete JSON text. The old restriction to objects and arrays came from RFC 4627 and was lifted."a/b" is fine, and "a\/b" means the same thing — a legacy habit from embedding JSON in HTML script tags.JavaScript parses every JSON number into an IEEE 754 double. Integers are exact only up to 9007199254740991, the value exposed as Number.MAX_SAFE_INTEGER. Feed the formatter {"id": 9007199254740993} and the output reads {"id":9007199254740992} — the document changed value, quietly, with no error anywhere. Snowflake IDs, Twitter-style identifiers, 64-bit database primary keys and nanosecond timestamps all live above that ceiling.
The same round trip normalises other spellings: 1.0 becomes 1, 1e2 becomes 100, -0 becomes 0. A value larger than a double can hold, such as 1e400, parses to infinity and serializes as null. Representation error is preserved rather than introduced: 0.30000000000000004 stays exactly that, being the shortest decimal that round-trips to the same double.
The rule is that any identifier you never do arithmetic on should travel as a string. If you cannot change the producer, do not run a large-integer payload through a JavaScript formatter before diffing it — the diff will show changes the network never made. That applies to every browser-based JSON tool, not just this one.
Sorting keys is the fastest way to make two structurally identical documents diff cleanly, so it is worth reaching for before a code review or a config comparison. The sort is lexicographic on the string form, not numeric or locale-aware: keys "1", "2" and "10" sort as 1, 10, 2, and uppercase sorts before lowercase by code point, so "Zebra" precedes "apple".
Separately, JavaScript places integer-like keys first in ascending numeric order regardless of insertion or sort order. Format {"b":1,"2":2,"a":3,"10":4} without sorting and the output begins {"2":2,"10":4, then "b", then "a". That is the language's property enumeration rule, not a choice the tool made, and it is one more reason a map keyed by ID is usually better modelled as an array of objects.
| Format | Adds | Typical home | Parses here? |
|---|---|---|---|
| JSON (RFC 8259) | — | APIs, wire formats, storage | Yes |
| JSONC | // and /* */ comments, usually trailing commas | tsconfig.json, VS Code settings | No — strip comments first |
| JSON5 | Comments, unquoted keys, single quotes, trailing commas, hex, leading/trailing decimal points, Infinity, NaN | Hand-edited config | No |
| NDJSON / JSON Lines | One complete JSON value per line, no wrapping array | Log pipelines, bulk export, streaming | One line at a time |
A file named .json that a strict parser rejects on a comment is almost always JSONC. Strip the comments rather than hoping every consumer is lenient: tolerance is a property of one parser, not of the format. NDJSON gives itself away as Unexpected non-whitespace character after JSON at the start of line two. To inspect one record, copy that line; to convert a whole file, wrap the lines in brackets and join them with commas, which yields ordinary JSON.
Minifying strips every byte of insignificant whitespace. It changes nothing semantic, so it is safe on the way out and reversible on the way in. It earns its keep wherever the document is transmitted or stored at volume — request bodies, queue messages, cache values, database columns — and in any field with a hard size cap such as a cookie, a URL parameter, or a log line a collector will truncate.
Where it does not help is anywhere the transport already compresses. Indentation is highly repetitive, so gzip or brotli removes nearly all of its cost and minifying an already-compressed response is close to a rounding error. Against that, a minified document is unreadable in logs and produces useless diffs. Keep the indented form in version control and minify at the edge.
Everything happens in one browser tab, so the ceiling is that tab's memory and DOM responsiveness, not a server limit. Parsing is fast; rendering is what gets slow, because a formatted megabyte becomes an enormous number of DOM nodes. Practical tactics:
jq, which does not need the whole document resident.The statistics strip is useful for sizing work before you do it: max depth tells you how nested a response is before you write the access path, and key and array counts tell you whether a slow-feeling payload is genuinely large or merely deeply nested.
Turn on Auto-Redact and the tool masks values matching recognisable secret shapes — AWS access keys, bearer tokens, JWTs, GitHub, Slack, Stripe and OpenAI-style keys, PEM private key headers, long hex strings and UUIDs — plus personal fields such as emails, phone numbers, card-shaped digit strings and SSNs. It also masks values under key names implying a secret: password, secret, token, api key, credential, authorization, client secret, cvv, pin. A badge shows how many were masked, and a zero on a payload you expected to contain a key means the pattern did not match, so check by eye.
Treat it as a safety net, not a guarantee: a high-entropy value under an innocuous key name may not match, and business data such as account numbers or internal hostnames is not what the patterns look for. Read the redacted output before pasting it anywhere. Redaction runs before formatting, so what you copy, download or share is the masked document.
Paste the raw response exactly as received — the mess is the evidence. If it fails, read the error shape: a named-construct message with a position points at a syntax slip near that offset, while a bare-token message points at a foreign literal such as NaN, None, True or undefined, which usually means the producer serialized with the wrong library. Unexpected end of JSON input means an empty body, so check the status code, and a truncation error mid-array means a timeout or size limit upstream, not a formatting bug.
Once it parses, use Tree View to confirm types rather than trusting the visual shape — "1" and 1 look nearly identical in indented text and behave very differently downstream. Then sort keys and minify for a canonical form and diff that, so two environments' responses compare without whitespace or ordering noise. The chain buttons under the output pass the formatted document straight into the diff checker, the format converter, base64 and URL encoders, or a hash generator.
A JSON formatter takes minified or poorly structured JSON (JavaScript Object Notation) and reformats it with consistent indentation, line breaks, and alignment for human readability. JSON is the dominant data interchange format used by REST APIs, configuration files, NoSQL databases, and modern web applications. While machines parse minified JSON efficiently, developers need formatted output to read, debug, and understand data structures.
Raw API responses, log entries, and configuration files often contain dense, single-line JSON that is impossible to scan visually. A JSON formatter instantly transforms {"name":"John","address":{"city":"Austin","state":"TX"},"tags":["admin","active"]} into a clearly indented, multi-line structure where nesting levels, arrays, and key-value pairs are visually distinct.
JSON formatting is a parsing and serialization process:
JSON data types:
| Type | Example | Notes |
|---|---|---|
| Object | {"key": "value"} | Unordered key-value pairs |
| Array | [1, 2, 3] | Ordered list of values |
| String | "hello" | Must use double quotes |
| Number | 42, 3.14, -1 | No leading zeros, no NaN/Infinity |
| Boolean | true, false | Lowercase only |
| Null | null | Lowercase only |
Common formatting options:
JSON formatting (pretty-printing) adds indentation, line breaks, and spacing to make JSON human-readable. Converts: {"name":"John","age":30} to multi-line indented format. Preserves data, improves readability. Used for: debugging API responses, reviewing config files, code documentation. Minification reverses process - removes whitespace for smaller file size. Most IDEs auto-format JSON. Online tools useful for: large files, comparing versions, sharing formatted data.
JSON validation checks structure against specification (RFC 8259). Common errors: missing quotes, trailing commas, unescaped characters, duplicate keys, invalid Unicode. Valid JSON requires: double quotes (not single), no trailing commas, escaped special chars (\n, \t, \"), UTF-8 encoding. Tools: JSON.parse() (JavaScript), json.loads() (Python), online validators. Error messages show: line/column number, error type, context. Fix errors before using JSON in production.
Common JSON errors: 1) Trailing commas - {"a":1,} (invalid). 2) Single quotes - {'name':'John'} (use double quotes). 3) Unescaped characters - {"path":"C:/folder"} (forward slash works, backslash needs escaping). 4) Missing commas/brackets - syntax errors. 5) Duplicate keys - {name:a, name:b} (last wins). 6) Comments - JSON does not support // or /* */ comments. 7) NaN/Infinity - use null instead. 8) Leading zeros - 0123 invalid (use 123).
Minification removes all unnecessary whitespace, line breaks, and formatting. Reduces file size by 20-50% for transmission/storage. Example: {"name": "John"} → {"name":"John"}. Use for: API responses, config deployment, bandwidth optimization. Trade-off: harder to debug. Process: remove spaces around {, :, [, remove line breaks, preserve string content. Tools: uglify-js, online minifiers. Production APIs: minify responses, keep source formatted. Use gzip compression for additional 60-80% reduction.
JSON Schema defines JSON structure, types, constraints. Validates: data types (string, number, object), required fields, value ranges, regex patterns, enum values, nested structures. Example schema: {"type":"object","properties":{"age":{"type":"number","minimum":0}}}. Used for: API contract validation, config file validation, form validation. Tools: ajv (JavaScript), jsonschema (Python). Provides: detailed validation errors, documentation, auto-completion in IDEs. Version: Draft 2020-12 latest.
JSON comparison (diff) identifies differences between files. Approaches: 1) Structural comparison - compare parsed objects, ignore formatting. 2) Text diff - line-by-line comparison (affected by formatting). 3) Deep comparison - recursive object comparison. Challenges: key order ({"a":1,"b":2} vs {"b":2,"a":1}), formatting differences, array order. Tools: jq (command-line), jsondiffpatch, online comparators. Use cases: config changes, API version differences, debugging. Normalize before comparing (sort keys, format).
JSONPath queries JSON structures similar to XPath for XML. Syntax: $ (root), . (child), .. (recursive), * (wildcard), [] (array subscript). Examples: $.store.book[*].author (all authors), $..price (all prices). Used for: extracting data from nested JSON, API response filtering, config queries. Implementations: JavaScript (jsonpath), Python (jsonpath-ng), command-line (jq). Alternative: jq filter language (more powerful). Use for complex JSON parsing without full parsing.
Large JSON files (100MB+) require streaming/specialized tools. Techniques: 1) Streaming parsers - process chunks without loading entire file. 2) jq (command-line) - efficiently filters large files. 3) MongoDB/databases - import JSON, query efficiently. 4) Compression - gzip reduces size 70-90%. 5) Split into smaller files. 6) Use NDJSON (newline-delimited) for streaming. Avoid: JSON.parse() on large files (memory issues), browser-based tools (crash). Use: jq, Python ijson library.