JSON Formatting Best Practices for Developers
Learn JSON formatting best practices: avoid common errors, validate, pretty-print, and master APIs with practical tips and real examples.
What is JSON and why does formatting matter?
JSON (JavaScript Object Notation) is the de facto data interchange format of the web. It is lightweight, human-readable, and supported by virtually every programming language. Whether you are building a REST API, storing configuration, or moving data between a frontend and a backend, JSON is almost always the format of choice.
But "human-readable" depends on how you write it. A single line of minified JSON may be 4 KB; the same data pretty-printed with two-space indentation may be 8 KB. Both are valid. The difference is whether the next developer β including future you β can read it at 2 AM during an incident.
Good formatting is not just about aesthetics. It directly affects:
- Debuggability: A pretty-printed payload shows structure at a glance. Nested objects are easy to navigate, missing keys are obvious, and typos jump out.
- Diff readability: Code reviews on minified JSON are useless. A two-space-indented diff clearly shows which fields changed.
- Error localization: When parsing fails, line and column numbers only make sense if the document has a real layout.
- Collaboration: A consistent style across a team means nobody wastes time reformatting files before they can work with them.
In short, formatting is a form of communication. Treat your JSON the same way you treat your code.
The most common JSON errors
Even seasoned developers make these mistakes. They are not syntax errors in JavaScript, which is why they slip through the editor unnoticed.
Trailing commas
A trailing comma after the last element of an array or object is perfectly valid JavaScript. JSON does not allow it.
```json // INVALID { "name": "Ada", "age": 36, } ```
The fix is trivial: remove the comma. Most linters catch this. If yours does not, switch to one that does.
Single quotes for strings
JSON strings must use double quotes. Single quotes are a JavaScript convention, not a JSON one.
```json // INVALID { 'name': 'Ada' } ```
This often bites developers who copy a value out of a JavaScript object literal or a Python dictionary rendered with single quotes. Always use double quotes for both keys and string values.
Unquoted keys
Keys in JSON must be strings, and strings must be quoted.
```json // INVALID { name: "Ada" } ```
Comments
JSON does not support comments. `//` and `/ /` will both fail to parse. If you need annotations, use a sidecar file, a separate `"_comment"` field, or migrate to JSON5 or JSONC β but only on the producer side, since most consumers expect strict JSON.
Mismatched brackets and braces
A missing `}` or an extra `]` is the most common source of "Unexpected end of JSON input" and similar errors. Pretty-printing is the fastest way to find these: your eyes will spot the imbalance immediately.
How to validate JSON
Validation falls into two categories: syntactic (is this well-formed JSON?) and semantic (does this match the schema I expect?).
For syntactic validation, every modern editor has you covered. VS Code highlights malformed JSON in red. The CLI tool `jq` will tell you on the first character that fails. Online validators work but be careful with sensitive data β paste only non-sensitive samples.
For semantic validation, you need a JSON Schema (more on that below) or a typed parser in your language of choice. In TypeScript, libraries like `zod` or `io-ts` let you describe the expected shape and reject anything that does not match. This catches the worst class of bug: the API silently returns a new field, or an old field becomes `null`, and your code crashes three layers down.
A good workflow is:
- Pretty-print incoming JSON while debugging.
- Validate against a schema at the boundary of your system (controller, API client, message handler).
- Trust nothing inside the boundary.
Pretty-printing vs. minification
These are two sides of the same coin, and both are useful β just in different places.
Pretty-print (also called "beautify" or "expand") adds indentation and line breaks. Use it for:
- Source files you commit to git
- API responses you inspect during development
- Log entries where you might need to read them later
- Documentation and examples
Minify strips all whitespace. Use it for:
- Production API responses
- Tokens and cookies (JWT, session storage)
- Storage in size-constrained databases or caches
- Network payloads where every byte matters
A practical rule: pretty-print in development, minify in production. Most build tools can do this automatically. For ad-hoc work, a free JSON Formatter handles both directions in a single paste.
If you need to compare two JSON documents, a text diff tool will highlight exactly which fields changed β far more useful than squinting at minified output.
Working with nested data
Nested objects and arrays are where JSON's expressiveness shines β and where bugs love to hide.
A few principles:
- Keep nesting shallow. Three levels is fine. Five levels means you should probably model the data as a flat list with foreign keys, or split it into multiple endpoints.
- Be consistent with arrays vs. objects. A field that is sometimes an array and sometimes `null` is a common source of `Cannot read property 'map' of null`. Decide upfront: if there are zero items, return `[]`, not `null`.
- Use stable key ordering when it matters. JSON does not require key order, but parsers and diff tools behave better when ordering is predictable. Alphabetical is a safe default.
- Watch out for large arrays. A 50 MB JSON blob with one million items in an array is technically valid but impossible to stream. Consider NDJSON (one JSON object per line) or a paginated API.
JSON in APIs: content-type and status codes
If you build HTTP APIs, two headers do most of the work:
- `Content-Type: application/json` β tells the client (and any intermediary) what to expect. Forgetting this is the single most common API bug in the wild.
- `Accept: application/json` β what the client is willing to receive. Useful for content negotiation.
On the response side, match the status code to the outcome:
- `200 OK` β success, body contains the resource or result.
- `201 Created` β a new resource was created; the `Location` header should point to it.
- `204 No Content` β success, no body (common for DELETE).
- `400 Bad Request` β the request was malformed (invalid JSON, missing required field).
- `401 Unauthorized` β no valid credentials.
- `403 Forbidden` β credentials are valid but lack permission.
- `404 Not Found` β the resource does not exist.
- `422 Unprocessable Entity` β JSON is valid but semantically wrong (e.g., negative age).
- `500 Internal Server Error` β something blew up on the server. Never leak stack traces.
A common pattern is to wrap responses in an envelope: `{ "data": ..., "error": null }` or `{ "data": null, "error": { "code": "...", "message": "..." } }`. This is fine, but not required. Either is better than inconsistent ad-hoc shapes.
JSON Schema basics
JSON Schema is a vocabulary that lets you describe the shape and constraints of a JSON document. Think of it as a type system for JSON.
A minimal schema:
```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "required": ["name", "age"], "properties": { "name": { "type": "string", "minLength": 1 }, "age": { "type": "integer", "minimum": 0 } } } ```
This says: the document must be an object with a non-empty string `name` and a non-negative integer `age`. You can extend it with formats (`"format": "email"`), enums, regex patterns, and references to other schemas.
Why bother? Validation at the boundary catches bad data before it propagates. It also serves as living documentation: the schema describes what your API actually accepts, not what someone thinks it accepts.
Most languages have a JSON Schema validator. TypeScript tools like `zod` are increasingly popular because they generate TypeScript types from the schema for you.
Common pitfalls with dates, numbers, and special characters
JSON is intentionally minimal. It does not have a date type, and that trips up everyone.
- Dates: store them as ISO 8601 strings (`"2026-02-01T12:00:00Z"`). Avoid formats like `"02/01/2026"` β ambiguous and locale-dependent.
- Numbers: JSON numbers are decimal. There is no integer type. Large integers above 2^53 lose precision in JavaScript. For IDs or money, prefer strings.
- Booleans: only literal `true` and `false`. Strings like `"true"` will not coerce automatically.
- Unicode: JSON strings are Unicode, so emojis and CJK characters are fine. But the escape sequences matter: `\n` is a newline, `\\` is a backslash, `\u0041` is `A`. When in doubt, paste your data into a JSON Formatter and inspect the raw bytes.
- Null vs. missing: `{"age": null}` and `{}` mean different things. Decide which one represents "unknown" in your system, and use it consistently.
Tools that save your time
A good formatter is one of those tools you do not realize you need until you use one. Our free JSON Formatter runs entirely in your browser β no upload, no signup, no tracking. Paste a minified payload, get a readable tree, copy it back. It validates as it formats, so syntax errors show up inline with a pointer to the offending line.
For comparing two versions of a JSON document β say, before and after a migration β the text diff tool does the same job for any plain text, with line-by-line highlighting.
Both are part of a broader set of developer tools designed for the kind of quick, in-browser utilities that you reach for dozens of times a day.
Conclusion
JSON formatting is one of those small disciplines that compounds over the course of a project. Pretty-print in development, minify in production. Validate at the boundary. Use schemas when the data is more than a one-off. Store dates as ISO 8601, large numbers as strings, and treat `null` with intention.
None of this is glamorous. All of it will save you hours of debugging the next time something goes wrong β and something always goes wrong. The good news is that with a formatter and a schema in your toolkit, the fix is usually a single paste away.