Pretty-print JSON without breaking it
A practical guide to formatting, validating and minifying JSON, with the pitfalls that trip up APIs and config files. Use the live JSON Formatter when you want the same steps in one click.
Why pretty-print at all?
Production payloads are often minified: one line, no spaces, hard to read in a log. Pretty-printing rewrites a valid JSON value with indentation so people can scan keys and nested arrays. Minifying does the reverse to make request bodies smaller. Both operations should parse first, then serialize. Inserting newlines by guesswork, or with a find-and-replace on commas, can produce invalid documents and can change strings that happen to contain commas or braces.
The safe sequence
- Treat the text as data, not as a string you clean up by hand.
- Parse it with a strict JSON parser:
JSON.parsein the browser, or your language's equivalent. - On success, serialize with a fixed indent (Fieldkit uses 2 spaces) or with no whitespace for minify.
- On failure, fix the syntax at the reported position. Do not ship the broken text.
Fieldkit's JSON Formatter & Validator follows that sequence in your tab: Format and Minify both parse, then call JSON.stringify.
Worked examples
Minified API response. Start with:
{"ok":true,"user":{"id":42,"roles":["admin","editor"]}}
Format produces:
{
"ok": true,
"user": {
"id": 42,
"roles": [
"admin",
"editor"
]
}
}
The values stay the same: true is still a boolean, 42 is still a number, and the strings keep their contents. Only whitespace changed. The pretty version is 98 bytes against 55 for the minified one, which is the whole point of minifying before sending.
Invalid trailing comma. This is legal in a JavaScript object literal but not in JSON:
{"name": "Fieldkit",}
A strict parser rejects it. In Chrome the message reads "Expected double-quoted property name", because after a comma the parser expects another key. Remove the comma after the last property and format again. Single-quoted strings, unquoted keys and // comments fail for the same reason: they are JavaScript syntax, not JSON.
Things formatting can change without warning
Parsing and re-serializing is safe for the structure, but it is not always byte-for-byte faithful to the original. These are the cases worth knowing, all reproducible in the formatter.
Duplicate keys disappear. RFC 8259 says object names SHOULD be unique and that behavior with duplicates is unpredictable. Browsers keep the last value. Format this webhook body:
{"event":"invoice.paid","amount":1200,"currency":"usd","amount":1500}
and you get three keys, with "amount": 1500. The 1200 is gone, and nothing tells you it was there. If two systems disagree about a value, check the raw text for a repeated key before trusting the formatted view.
Large integers lose digits. JSON numbers have no size limit in the grammar, but JavaScript stores them as IEEE 754 doubles, and RFC 8259 notes that only integers between -(253)+1 and 253-1 are reliably interoperable. {"order_id":9007199254740993} formats as "order_id": 9007199254740992. Database IDs and snowflake-style IDs should travel as strings when every digit matters.
Number spelling changes. 1.0 becomes 1, and 1e3 becomes 1000. The value is the same; the text is not. That matters if you diff formatted output against the original or compute a signature over the raw bytes.
Integer-like keys move to the front. JavaScript objects list keys that look like array indexes first, in numeric order. {"2":"x","1":"y","b":1,"a":2} comes back as {"1":"y","2":"x","b":1,"a":2}. Other keys keep their original order. JSON objects are unordered by definition, so no correct consumer should depend on order, but humans comparing files will notice.
Escapes are decoded. "caf\u00e9" comes back as "café". Both are the same string in JSON.
Invisible problems: BOMs and pasted characters
RFC 8259 says JSON sent between systems must be UTF-8 and that implementations must not add a byte order mark. Parsers may ignore one, but JSON.parse does not: text that starts with U+FEFF fails with an "Unexpected token" error at position 0, even though the editor shows nothing there. Files saved by some Windows editors start with a BOM. Re-save as UTF-8 without BOM, or delete the first character.
Copying from chat apps and word processors can also bring curly quotes (“ ”) instead of straight ones, or non-breaking spaces. The parser rejects curly quotes. Non-breaking spaces between tokens are also an error, since JSON only allows space, tab, line feed and carriage return as whitespace.
Values that are not JSON at all
NaN, Infinity and undefined do not exist in JSON. In JavaScript, JSON.stringify({a: NaN}) writes {"a":null}, and properties whose value is undefined or a function are dropped. Python's json.dumps goes the other way by default and writes NaN, which strict parsers then reject. If a payload works in one language and fails in another, search for these tokens.
Two values in one paste, like {}{}, are not one JSON document either. The parser stops after the first value and reports unexpected text. Wrap them in an array or handle one document at a time.
Valid JSON is not the same as correct data
The formatter checks syntax: the text is one well-formed JSON value. It does not know what the receiving API expects. {"amount":"12.50"} is valid JSON even if the API wants a number, and a body with a required field missing is still valid JSON. Checking types, required fields and allowed values is the job of a schema. JSON Schema is the common choice, and most languages have a validator for it. A practical order is to format first so the structure is readable, then compare it with the API documentation, and let a schema check in your tests catch the rest.
Formatting from the command line
When the JSON lives in a file or a pipeline, use a local tool:
python3 -m json.tool file.jsonpretty-prints with a 4-space indent and fails with a line and column on invalid input.jq . file.jsonpretty-prints with 2 spaces.jq -c .minifies, andjq -S .sorts keys, which makes two files easy to diff.- In JavaScript,
JSON.stringify(value, null, 2)is what the formatter runs. Pass"\t"instead of2for tabs.
When to use Fieldkit and when to use your editor
Use the browser tool when a log line or webhook body lands in chat and you need a quick read, or when you want the Keys and Depth counts to compare two payloads. Use your editor or CI when the file lives in a repo, needs formatting on save, or must match a project's lint rules. For spreadsheet export of arrays of objects, see the JSON to CSV guide and the JSON to CSV Converter.
Open the live tool
Open JSON Formatter & Validator Related reading: all guides · FAQ.