How to prettify compact json for debugging
- Step 1Capture the compact JSON to a file — Save the minified API response, the logged JSON string, or the copied webhook body to a
.jsonfile. The tool takes a file, not a paste box — write the string out (for examplepbpaste > resp.jsonon macOS, or save from your browser's network panel). - Step 2Drop or browse the file onto the tool — Drag the
.jsonfile onto the dropzone above, or clickbrowse. The file is read in your browser withfile.text(); nothing uploads. - Step 3Pick the indent width — Choose
2 spaces(default, compact for narrow editors) or4 spaces(easier to follow deep nesting in a wide terminal). Those are the only two options — there is no tab or custom-width setting. - Step 4Toggle key sorting when comparing two responses — Enable
Sort keys alphabeticallywhen you want to diff two captures of the same endpoint. Sorting is recursive (every nested object) and uses locale-aware ordering, soapplesorts beforeBananarather than after it. - Step 5Click Prettify JSON and read the result — The formatted output renders in a scrollable panel. The preview truncates at 5,000 characters for display only — Copy and Download still return the full document. The header shows input → output byte sizes.
- Step 6Copy or download for your bug report — Copy pastes the full prettified JSON to your clipboard for a ticket or GitHub comment; Download saves it as
<name>.pretty.json. Wrap it in a fenced ```json block so it stays readable in Markdown.
Options the prettifier actually exposes
The complete control set from lib/json-prettifier.ts and the tool client. There are exactly two options — anything else you may have seen on other formatters does not exist here.
| Control | Values | Default | What it does |
|---|---|---|---|
| Indent | 2 spaces or 4 spaces | 2 spaces | Sets JSON.stringify's indent argument. No tab option, no 0/1/3/8-space option, no minify mode — for compact output use json-minifier. |
| Sort keys alphabetically | on / off | off | When on, applies a JSON.stringify replacer that re-emits every object's entries sorted by a.localeCompare(b). Recursive at all nesting levels. Arrays keep their order — only object keys move. |
| Input | one .json file (drop or browse) | — | Reads a single file via file.text(). No paste textarea, no multi-file batch on free tier (free JSON batch is 1 file). |
What parses and what throws
The tool uses strict JSON.parse(text.trim()). Inputs in the right column error with invalid JSON: <message> and produce no output — fix them upstream first.
| Accepted (parses cleanly) | Rejected (throws a parse error) |
|---|---|
| Standard RFC 8259 JSON object or array | Trailing comma {"a":1,} → use json-format-fixer |
| Leading/trailing whitespace (trimmed) | // or /* */ comments (JSONC) → repair first |
A bare top-level value (42, "hi", true, null) | Single-quoted strings or unquoted keys → repair first |
| Deeply nested objects and arrays | NaN, Infinity, -Infinity, undefined |
| Unicode, escaped sequences, emoji | NDJSON / concatenated objects {...}\n{...} (not one document) |
Same input, both indent widths
How the two available widths render identical data. Use 2-space for narrow side-by-side panels, 4-space when nesting gets deep.
| Setting | Output |
|---|---|
| 2 spaces | {\n "id": 42,\n "ok": true\n} |
| 4 spaces | {\n "id": 42,\n "ok": true\n} |
Cookbook
Real debugging captures, before and after. All tokens and IDs are synthetic.
Minified API response made readable
ExampleA REST endpoint returns a compact body. Prettify at 2-space to see the envelope structure at a glance during debugging.
Input (single line):
{"data":{"user":{"id":42,"name":"Ada"}},"meta":{"trace":"7f3a"},"errors":[]}
Output (2-space):
{
"data": {
"user": {
"id": 42,
"name": "Ada"
}
},
"meta": {
"trace": "7f3a"
},
"errors": []
}Sort keys to diff two responses
ExampleThe same endpoint serialized fields in different orders across two deploys. Sorting keys makes the two prettified outputs diff cleanly so the only highlighted line is the real change.
Capture A: {"name":"Ada","id":42,"role":"admin"}
Capture B: {"id":42,"role":"user","name":"Ada"}
Both prettified with Sort keys ON:
A: B:
{ {
"id": 42, "id": 42,
"name": "Ada", "name": "Ada",
"role": "admin" "role": "user" <- only real diff
} }Parse check catches a malformed payload
ExampleA copied response had a trailing comma left by a hand-edit. The tool refuses to format it and tells you exactly where — that is the bug, not the formatting.
Input:
{"a":1,"b":2,}
Result:
invalid JSON: Expected double-quoted property name in
JSON at position 13 (line 1 column 14)
Fix the trailing comma (or run json-format-fixer), then
re-prettify.Big integer ID silently loses precision
ExampleA Twitter/Snowflake-style 64-bit ID exceeds JavaScript's safe integer range. JSON.parse rounds it — this is a real data-corruption trap, not a formatting choice. Keep such IDs as strings at the source.
Input:
{"tweet_id":12345678901234567890}
Output:
{
"tweet_id": 12345678901234567000
}
The last digits changed. If you need the exact ID,
the API must emit it as a string: "12345678901234567890".Round-trip with the minifier in a test case
ExamplePrettify to inspect a fixture, then minify it back to a single line to drop into an inline assertion.
Pretty (read in editor):
{
"ok": true,
"count": 3
}
Run json-minifier ->
{"ok":true,"count":3}
Paste back into the test. No data changed, only whitespace.Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
Input has a trailing comma or // comment
Parse errorStrict JSON.parse rejects JSONC. You get invalid JSON: Expected ',' or '}' after property value (or a property-name error for the trailing comma). The prettifier does not strip these — run json-format-fixer first, which removes trailing commas, quotes unquoted keys, and converts single quotes, then prettify the repaired output.
Pasting a multi-line NDJSON log dump
Parse errorNDJSON (one JSON object per line) is not a single JSON document, so JSON.parse throws Unexpected non-whitespace character after JSON. Prettify one line at a time, or for log-line formatting see the structured-log guide. This tool formats exactly one value per run.
64-bit integer ID in the payload
Silent precision lossJavaScript numbers are IEEE-754 doubles, so any integer above 9,007,199,254,740,991 is rounded on parse — 12345678901234567890 becomes 12345678901234567000. The output is valid JSON but the value changed. There is no BigInt mode; the only safe fix is for the producing API to emit large IDs as JSON strings.
Object has duplicate keys
Last value wins{"a":1,"a":2} is technically allowed by the grammar but JSON.parse keeps only the last occurrence, so the output is {"a":2} and the first value is silently dropped. If you suspect a duplicate-key bug in a producer, this tool will hide it — inspect the raw bytes instead.
Numeric-string keys like "0", "1", "2"
Reordered by the engineJavaScript objects place integer-like keys first, in ascending numeric order, before any string keys — regardless of the Sort keys toggle. {"b":1,"2":2,"1":3} re-emits as {"1":3,"2":2,"b":1}. Key order is therefore not always byte-preserved; if exact order matters, keep the data as an array.
Sort keys with mixed case
Locale order, not ASCIISorting uses localeCompare, so apple, Banana, cherry sort as apple, Banana, cherry — not the ASCII/code-point order (Banana, apple, cherry) that jq -S produces. This is fine for human reading but means the byte output can differ from a jq-sorted file; pick one tool consistently for diff stability.
Numbers like 1e3, 0.10, 1.0
NormalizedJSON.parse then stringify canonicalizes numbers: 1e3 becomes 1000, 0.10 becomes 0.1, and 1.0 becomes 1. The mathematical value is identical, but the literal text changes — keep this in mind if you are byte-diffing prettified output against a hand-formatted original.
Top-level value is a string or number, not an object
SupportedA bare 42, "hello", true, or null is a valid JSON document and prettifies fine (indent has no visible effect on a scalar). This is expected — JSON's top level need not be an object or array.
File larger than 2 MB on the free tier
Rejected — over tier limitFree JSON tier caps a single file at 2 MB. Larger debug captures are blocked with an upgrade prompt; Pro raises the JSON file limit to 100 MB. Very large documents also hit the in-browser 5,000-character preview truncation — that is display only; Copy and Download still return the whole document.
Empty file or only whitespace
Parse errorAfter text.trim(), an empty string is not valid JSON, so you get invalid JSON: Unexpected end of JSON input. Confirm you actually saved the response body and not an empty placeholder.
Frequently asked questions
Does this tool strip trailing commas or comments like my editor does?
No. The prettifier uses strict JSON.parse, which rejects trailing commas, // and /* */ comments, single quotes, and unquoted keys. Those features belong to JSONC, not JSON. Run json-format-fixer first to repair them, then prettify the cleaned output.
What indent widths can I choose?
Exactly two: 2 spaces (the default) and 4 spaces. There is no tab option and no custom width, despite what some older copy elsewhere on the site may imply — the underlying type is 2 | 4. For zero-whitespace output, use json-minifier instead.
Why did my large ID number change after prettifying?
JavaScript parses all JSON numbers as 64-bit floats, so any integer above 2^53−1 (9,007,199,254,740,991) is rounded. A 19-digit Snowflake or Twitter ID will lose its last few digits. This is a parsing limitation, not a formatting bug. The fix is upstream: the API should emit large IDs as JSON strings.
Can I paste JSON into the tool, or do I need a file?
The tool reads a file you drop or browse to — there is no paste textarea. Save your captured response to a .json file first. If you only have a clipboard string, write it out (for example pbpaste > resp.json) and drop that file.
Does Sort keys change my array order?
No. Sorting only reorders the keys inside objects; array element order is always preserved. Sorting is recursive, so nested objects are sorted too, and it uses locale-aware comparison (apple before Banana).
Will it tell me where my JSON is broken?
Yes — on a parse failure it surfaces the JSON.parse message including the position, for example invalid JSON: Expected ',' or '}' after property value (line 4 column 3). That makes it a quick syntax check as well as a formatter. For a richer line-by-line report use json-validator.
Is the prettified output byte-identical to jq's?
Not necessarily. Key sorting here uses localeCompare while jq -S sorts by Unicode code point, and number canonicalization rules differ slightly. The values are equivalent, but the exact bytes can differ. For diff-stable commits, standardize on one tool across the project.
Can it format a whole array of API responses at once?
Only if they are a single JSON array — [{...},{...}] parses and prettifies fine. A newline-separated stream of objects (NDJSON) is not one document and will error. Wrap your captures in [ ... ] first if you want them formatted together.
Does prettifying ever change my data?
Only in three documented ways, all from JSON.parse round-tripping: large integers lose precision, duplicate keys collapse to the last value, and number literals are canonicalized (1e3 → 1000). Otherwise keys, values, strings, and structure are preserved exactly — only whitespace is added.
Why does the preview look cut off?
The on-screen preview truncates at 5,000 characters with a …(truncated) marker to keep the page responsive. This is display-only — the Copy button and Download button both return the complete prettified document.
Is my debug payload uploaded anywhere?
No. Parsing and formatting run entirely in your browser via JSON.parse/JSON.stringify. API response bodies, bearer tokens, and any PII in the payload never reach JAD Apps servers. Only an anonymous run counter is recorded when you are signed in.
Can I run this in an automated debugging pipeline?
Yes, on Pro. The json-prettifier runner bundle (runner-local, tier pro) mirrors the browser logic exactly — it clamps indent to 2 or 4, supports sortKeys, and trims before parsing. Pair the runner once and pass { indent, sortKeys } to format captured responses locally without anything leaving your machine.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.