JSON Formatting Best Practices for APIs (2026)
JSON looks simple — until you ship a public API and discover that "valid JSON" varies between languages, that 2^53 breaks numbers in JavaScript, and that ISO 8601 dates round-trip differently in Go vs Python. This is the 2026 reference for JSON formatting in production APIs.
Indentation: 2 spaces, no tabs
The unwritten standard in 2026 is 2-space indentation, LF line endings, no trailing whitespace. Reasons: smaller diffs, consistent rendering across editors, and tabs render inconsistently in browser-based viewers.
For machine-to-machine traffic, send minified (no whitespace). For developer-facing endpoints (e.g., docs, debug pages), pretty-print with 2 spaces. Use our JSON formatter to switch between modes.
Key ordering: stable, predictable
JSON objects are technically unordered, but every consumer treats key order as meaningful — diff tools, change detection, content hashes. Recommendations:
- Server side: serialise with insertion order preserved (Python dict in 3.7+, Go's
encoding/json, Node'sJSON.stringify) - For canonical hashing/signing: use RFC 8785 JCS (JSON Canonicalization Scheme) — sorts keys lexicographically
The 2^53 number problem
JSON numbers are 64-bit floats per the spec. JavaScript's Number can only represent integers exactly up to 2^53 (9,007,199,254,740,992). Any larger integer (Twitter snowflake IDs, Discord IDs, large primary keys) silently corrupts.
Solutions:
- Send IDs as strings — the most reliable cross-language fix
- Use BigInt-aware parsers server-side; not all clients support it
- Document the range — explicitly note "ID is uint64 sent as string"
Twitter's API uses id_str alongside id for exactly this reason.
Date formats: ISO 8601 with timezone
Always send dates as 2026-04-12T07:30:00Z (UTC, ISO 8601). Avoid:
- Unix timestamps as numbers — ambiguous (seconds vs milliseconds)
- Locale-dependent strings ("4/12/2026" — month or day first?)
- Timezone offsets without seconds (some parsers reject
+05:30)
Use our Unix timestamp converter when you need to debug timestamps in the wild.
Null vs missing keys
Three valid representations of an absent value:
{ "name": null }— explicitly null{ "name": "" }— empty string{}— key omitted
Pick one and stick with it. Null is the most semantically correct ("we know there's no value"), missing is the most compact ("we don't know"), empty string is usually wrong.
Booleans: lowercase only
JSON booleans are true and false, lowercase. Don't send "true" as a string. Don't send 1/0. Don't send "yes"/"no". Strict parsers will reject these.
Floating-point precision
Avoid sending 0.1 + 0.2 = 0.30000000000000004 in JSON. Round to the precision the consumer needs. For currency, use string representations ("123.45") or send integer cents (12345).
Arrays: empty vs missing
Always include the array key with [] if the field is "always-an-array but might be empty." This simplifies client logic — it can iterate without null-checking.
{ "items": [] } // Good - always an array
{ } // Bad - client must check existence first
Encoding: UTF-8, no BOM
Send JSON as UTF-8. Don't include a Byte Order Mark (BOM) — it breaks some parsers. Set Content-Type: application/json; charset=utf-8.
Wrapping the response
Two common patterns:
- Bare:
{ "id": 1, "name": "..." }— simple, restful - Wrapped:
{ "data": {...}, "meta": {...}, "errors": [...] }— JSON:API style, easier to extend
Pick one for your whole API. JSON:API style is verbose but pays off when you start adding pagination metadata.
Error responses: structured
Always return errors as JSON, not HTML or plain text:
{
"error": {
"code": "validation_failed",
"message": "Email is invalid",
"field": "email",
"docs": "https://docs.api.com/errors#validation_failed"
}
}
Validation: schema first
Define a JSON Schema (Draft 2020-12) for every endpoint. Tools: ajv, jsonschema, openapi. Use our JSON validator for ad-hoc checks during development.
The minimal-good-citizen response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"data": {
"id": "01HQZ...",
"created_at": "2026-04-12T07:30:00Z",
"name": "Example",
"is_active": true,
"tags": []
}
}
Tooling
- JSON formatter & beautifier — pretty-print, minify
- JSON validator — line-numbered errors
- JSON to CSV — quick exports for spreadsheets
- JSON to YAML — for Kubernetes configs
Bottom line
2-space indent, ISO 8601 dates, string IDs for >2^53, lowercase booleans, structured errors. Define a schema. Validate every payload. The boring choices in JSON formatting save you from hours of debugging at 2am.
Try the free dev tools suite
15+ tools. 100% client-side. No signup. No tracking.
Browse all tools →