JSON Formatter Complete Guide: Beautify, Minify, Validate, and Fix
JSON is the universal language of APIs, config files, and data exchange. But raw JSON from an API response is often a single unreadable line, while JSON you write by hand sometimes contains subtle errors that only surface at runtime. A good formatter does three things: makes JSON readable, makes it compact for transport, and catches errors before they reach production. Open the JSON Formatter to follow along.
Pretty-Print vs Minify: When to Use Each
The same JSON object can be represented in two extreme forms:
// Minified — for transport and storage
{"user":{"id":42,"name":"Jane Smith","active":true,"roles":["admin","editor"]}}// Pretty-printed — for reading and editing
{
"user": {
"id": 42,
"name": "Jane Smith",
"active": true,
"roles": [
"admin",
"editor"
]
}
}| Mode | Use When | Avoid When |
|---|---|---|
| Pretty-print | Debugging API responses, editing config files, code review, documentation, diffing two JSON payloads | Sending over the network, storing in databases, embedding in JS bundles |
| Minify | API responses, localStorage, cookies, URL query params, CI artifacts | Any file a human needs to read or edit directly |
The size difference matters at scale. A 50KB pretty-printed API response minifies to roughly 35KB — a 30% reduction with zero information loss. For responses served millions of times per day, that compounds quickly.
Indentation: 2 Spaces, 4 Spaces, or Tabs
Pretty-printing requires choosing an indentation unit. There is no universal standard for JSON specifically, but conventions exist by context:
| Indent | Common In | Tradeoff |
|---|---|---|
| 2 spaces | JavaScript ecosystem, package.json, most REST APIs, Prettier default | Compact; deeply nested structures still fit in 80 columns |
| 4 spaces | Python (json.dumps default), Java tooling, some style guides | More readable at shallow depth; deep nesting goes wide fast |
| Tabs | Some Go tooling, editors with tab-width preferences | Visually adaptable per editor; inconsistent in diff views |
In JavaScript, JSON.stringify takes an optional third argument for the indent:
const obj = { name: "Jane", active: true };
JSON.stringify(obj); // minified: '{"name":"Jane","active":true}'
JSON.stringify(obj, null, 2); // 2-space indent
JSON.stringify(obj, null, 4); // 4-space indent
JSON.stringify(obj, null, ' '); // tab indentJSON5 and JSONC: Comments and Trailing Commas
Standard JSON (ECMA-404) does not allow comments or trailing commas. This is intentional — JSON is a data interchange format, not a config language. But config files are often written by humans, and humans want comments.
Two non-standard supersets fill this gap:
JSONC (JSON with Comments)
Used by VS Code (settings.json, launch.json), TypeScript (tsconfig.json), and ESLint. Supports // and /* */ comments, and trailing commas:
// tsconfig.json is JSONC
{
"compilerOptions": {
"target": "ES2022", // minimum Node 18
"strict": true,
"moduleResolution": "bundler",
/* enables path aliases */
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"], // trailing comma is OK in JSONC
},
},
}JSON5
A more liberal superset that also allows unquoted keys, single-quoted strings, hexadecimal numbers, multi-line strings, and +Infinity / -Infinity:
// JSON5 example
{
// Unquoted keys
name: 'Jane Smith',
// Trailing comma in object and array
roles: ['admin', 'editor',],
// Hex numbers
flags: 0x1F,
// Multi-line string
description: 'Line one line two',
}If you paste JSONC or JSON5 into a strict JSON validator, it will reject the comments and trailing commas. The JSON Formatter handles both formats — it strips comments and trailing commas before parsing, so you can paste config files directly without pre-processing. See also the deeper dive in JSON Trailing Commas and Comments.
Validation: What Makes JSON Invalid
JSON has strict syntax rules. These are the errors that trip up developers most often:
1. Trailing commas
// Invalid JSON — trailing comma after last element
{
"name": "Jane",
"active": true, ← error
}2. Single quotes instead of double quotes
// Invalid — JSON requires double quotes for strings and keys
{ 'name': 'Jane' }
// Valid
{ "name": "Jane" }3. Unquoted keys
// Invalid — all keys must be quoted strings
{ name: "Jane" }
// Valid
{ "name": "Jane" }4. Comments
// Invalid — JSON has no comment syntax
{
// This is a user object
"name": "Jane"
}5. Undefined, NaN, Infinity
// Invalid — these JavaScript values have no JSON representation
{
"value": undefined,
"ratio": NaN,
"limit": Infinity
}
// Valid alternatives
{
"value": null,
"ratio": null,
"limit": 1.7976931348623157e+308
}6. Unescaped control characters in strings
// Invalid — raw tab or newline inside a string
{ "text": "line one
line two" }
// Valid — use escape sequences
{ "text": "line one
line two" }7. Numbers with leading zeros
// Invalid — octal ambiguity; JSON forbids leading zeros
{ "code": 007 }
// Valid
{ "code": 7 }Sorting Keys
JSON objects are technically unordered — the specification says key order is not guaranteed. In practice, most parsers preserve insertion order, but you should not rely on it.
Sorting keys is useful for:
- Diffing: Two JSON objects with the same data but different key order produce a noisy diff. Sort both before comparing.
- Caching: If you hash JSON for cache keys, unsorted keys can produce different hashes for identical data.
- Consistency in version control: Sorted keys mean git diffs only show actual data changes, not reorderings.
// Sort keys recursively
function sortKeys(obj) {
if (Array.isArray(obj)) return obj.map(sortKeys);
if (obj !== null && typeof obj === 'object') {
return Object.fromEntries(
Object.entries(obj)
.sort(([a], [b]) => a.localeCompare(b))
.map(([k, v]) => [k, sortKeys(v)])
);
}
return obj;
}
const sorted = JSON.stringify(sortKeys(data), null, 2);On the command line, jq sorts keys with the --sort-keys flag:
jq --sort-keys . input.json > sorted.jsonWorking with Large JSON Files
Pasting a 10MB JSON file into a browser-based formatter will work, but parsing and rendering a very large tree can be slow. For large files, command-line tools are faster:
# Pretty-print
jq . large.json
# Minify
jq -c . large.json
# Extract a nested value
jq '.users[0].profile.name' large.json
# Filter array
jq '[.users[] | select(.active == true)]' large.jsonFor streaming very large JSON (gigabyte-scale), jq uses streaming mode (--stream), or use ijson in Python for incremental parsing.
Formatting JSON in Code
JavaScript / TypeScript
// Pretty-print
const pretty = JSON.stringify(data, null, 2);
// Minify
const minified = JSON.stringify(data);
// With a replacer — exclude null values
const clean = JSON.stringify(data, (key, value) =>
value === null ? undefined : value
, 2);
// Parse safely
function safeParseJSON(str) {
try {
return { ok: true, data: JSON.parse(str) };
} catch (e) {
return { ok: false, error: e.message };
}
}Python
import json
# Pretty-print
print(json.dumps(data, indent=2, ensure_ascii=False))
# Minify (no spaces)
print(json.dumps(data, separators=(',', ':')))
# Sort keys
print(json.dumps(data, indent=2, sort_keys=True))
# Parse with error handling
try:
parsed = json.loads(raw_string)
except json.JSONDecodeError as e:
print(f"JSON error at line {e.lineno}, col {e.colno}: {e.msg}")Escaped Strings in JSON
A common gotcha: JSON received from an API sometimes has the entire payload double-encoded — the JSON object is serialised to a string, and then that string appears as a JSON value:
// Double-encoded: the value is a JSON string containing JSON
{
"payload": "{"user":{"id":42,"name":"Jane"}}"
}To work with the inner JSON, you need to parse twice — or use the Unescape JSON Strings tool to extract the inner payload first.
Quick Reference
| Task | Tool |
|---|---|
| Pretty-print or minify JSON | JSON Formatter |
| Validate JSON and see the exact error | JSON Formatter |
| Unescape a double-encoded JSON string | Unescape JSON Strings |
| Query nested values with dot-path syntax | JSONPath Tester |
| Convert JSON to CSV for spreadsheets | JSON ↔ CSV Converter |
| Validate JSON against a schema | JSON Schema Validator |
Format, validate, and explore JSON instantly in your browser with the JSON Formatter — no data leaves your machine.