The Formatted Response
Applying a formatter to the minified input above produces:
{
"status": "success",
"data": {
"users": [
{
"id": 1,
"name": "Alice Chen",
"email": "alice@example.com",
"role": "admin",
"created_at": "2024-01-15T08:30:00Z"
},
{
"id": 2,
"name": "Bob Martinez",
"email": "bob@example.com",
"role": "editor",
"created_at": "2024-03-22T14:15:00Z"
},
{
"id": 3,
"name": "Carol Williams",
"email": "carol@example.com",
"role": "viewer",
"created_at": "2024-06-10T11:45:00Z"
}
],
"total": 3,
"page": 1,
"per_page": 25
},
"meta": {
"request_id": "req_abc123",
"response_time_ms": 42
}
}
The structure is immediately readable: a success envelope wrapping a paginated user list plus request metadata.
Why Formatted JSON Matters for Debugging
When you curl an API and get back a wall of minified JSON, the first thing you do is pipe it through a formatter. The reason is practical: nested structures are invisible in a single line. You cannot scan for a missing key, spot a null value, or verify array length without indentation.
Formatted JSON makes several debugging tasks much faster:
- Spotting unexpected nulls or missing fields. When each key is on its own line, a missing field jumps out rather than hiding inside a long string.
- Verifying nesting. Deeply nested JSON in minified form requires manually counting braces and brackets. Indentation makes the tree structure visible instantly.
- Diffing responses. Two minified JSON blobs diff as a single changed line even if only one field changed. Pretty printed JSON diffs cleanly, showing exactly which field changed.
- Reading in code review. JSON test fixtures checked into version control should always be pretty printed so diffs are reviewable.
Common REST API Response Structures
The example above follows a widely used pattern: a top level status field, a data object containing the actual payload, and a meta object with request level information. Variations on this pattern appear constantly:
JSend-style envelope
{
"status": "success",
"data": { ... }
}
JSON:API envelope
{
"data": [ ... ],
"links": { "next": "...", "self": "..." },
"meta": { "total": 42 }
}
Error response
{
"status": "error",
"code": "RESOURCE_NOT_FOUND",
"message": "User 99 does not exist",
"request_id": "req_xyz789"
}
Formatting any of these makes the envelope structure immediately obvious, which helps when you are writing a client and need to understand what path to traverse to reach the data you want.
Indentation Conventions
The two dominant choices are 2 spaces and 4 spaces. Tabs are also valid JSON whitespace but less common in shared configuration.
2 spaces is the default in many JavaScript tools. JSON.stringify(obj, null, 2) and jq both produce 2-space output. It keeps nested structures compact, which matters if you routinely work with deeply nested JSON.
4 spaces is the Python convention. json.dumps(obj, indent=4) is the most common Python snippet you will find. It is also the default in many IDE formatters.
Pick based on what your team already uses. If you have a .editorconfig or a project level Prettier configuration, it already specifies the indent size. Use that. Do not mix indent widths in the same file or the same repository.
Formatting JSON on the Command Line
jq is the standard tool for command line JSON formatting and querying. Install it once (brew install jq or apt install jq) and you will use it constantly.
Format a raw string:
echo '{"name":"Alice","role":"admin"}' | jq .
Format a file:
jq . response.json
Format a curl response inline:
curl -s https://api.example.com/users | jq .
Extract a nested value while formatting the response:
curl -s https://api.example.com/users | jq '.data.users[0].email'
If jq is not available, Python’s standard library covers the basic case:
echo '{"name":"Alice"}' | python3 -m json.tool
Or, using Node.js:
node -e "process.stdin.pipe(require('stream').pipeline ? process.stdin : process.stdin)" \
<<< '{"name":"Alice"}' | node -e "let d=''; process.stdin.on('data', c => d+=c); process.stdin.on('end', () => console.log(JSON.stringify(JSON.parse(d), null, 2)))"
That is verbose. Use jq.
Minification for Production
Serving minified JSON reduces payload size, but the impact is context dependent:
| Response size | Whitespace overhead | Compressed gain from minifying |
|---|---|---|
| 1 KB | ~15-25% | Negligible after gzip |
| 100 KB | ~15-25% | Modest (~2-5% of compressed) |
| 10 MB static file | ~15-25% | Meaningful without compression |
Enable HTTP compression (Content-Encoding: gzip or br) before worrying about minification. Whitespace compresses extremely well. Gzip compresses repetitive indentation to nearly nothing. If you already compress your API responses, the extra step of minifying JSON produces diminishing returns.
Where minification unambiguously helps: large static JSON assets served without consistent compression. Translation files, GeoJSON datasets, and bundled configuration files are good candidates.
Validating JSON While Formatting
A formatter that parses JSON before re emitting it also validates the input. If your JSON has a syntax error (a trailing comma, an unquoted key, a missing bracket), the formatter will catch it and show you where the parse failed. This is a faster feedback loop than deploying code and waiting for a runtime JSON parse error.
Common JSON syntax mistakes:
- Trailing commas after the last key in an object or last element in an array. Valid in JavaScript object literals but not in JSON.
- Single quoted strings. JSON requires double quotes everywhere.
- Unquoted keys.
{name: "Alice"}is JavaScript, not JSON. - Comments. JSON has no comment syntax.
//or/* */will cause a parse failure.
If you need a JSON like format with comments and trailing commas, look at JSON5 or JSONC, but be aware that standard JSON parsers will reject them.