JSON has become the universal language of web APIs. Nearly every REST API, webhook, and configuration file uses it. Yet despite its apparent simplicity — it is just key-value pairs and arrays — poorly structured JSON creates real problems: API clients break on unexpected nulls, date parsing fails across timezones, and inconsistent naming conventions make codebase-wide changes painful. A handful of consistent decisions made early in an API's lifetime prevent months of bugs later.
Naming Conventions: Pick One and Enforce It
The two dominant conventions are camelCase (firstName, createdAt) and snake_case (first_name, created_at). camelCase is the JavaScript convention and feels natural when consuming APIs in JS/TS. snake_case is preferred in Python and Ruby ecosystems. There is no universally "correct" choice — but consistency is mandatory.
Mixing conventions within the same API is the worst outcome. An API that returns userId in one endpoint and user_id in another forces every client to normalize the data before using it, doubling the error surface. If you are building a new API, choose one convention and document it. If you are extending an existing one, match what is already there.
Boolean fields should read as true statements: is_active, has_permission, can_edit. Avoid is_not_deleted or has_no_errors — negative booleans are cognitively harder to parse and make conditionals error-prone. The field name should read true when the value is true: user.isActive === true means the user is active.
Null, Missing, and Empty: They Are Not the Same
null means the field exists but has no value. A missing field means the field is not applicable in this context. An empty string "" or empty array [] means the field exists and is explicitly empty. These distinctions matter for API consumers: a null bio means "no bio set yet," while a missing bio field might mean "this endpoint does not return bios." Use them intentionally.
Avoid using null as a sentinel value for "unknown," "N/A," or "loading." Return a specific string like "unknown" or omit the field entirely. null should mean only one thing: the value is known to be absent. Overloading null with multiple meanings forces API clients to infer context from surrounding fields.
For arrays, return [] instead of null when there are no items. An empty array is a valid collection that clients can safely iterate — a null requires a null check before every loop. Similarly, return an empty object {} rather than null for nested objects when the concept exists but has no data.
Dates and Timestamps: Always Use ISO 8601
Date formatting is the most common source of API parsing bugs. Always use ISO 8601 format: 2025-06-07T14:30:00Z. This format is unambiguous, parseable by every modern programming language's standard library, sortable as a string, and includes timezone information. A date string like "06/07/2025" is ambiguous (is that June 7th or July 6th?) and locale-dependent.
Always include timezone information. Storing and transmitting dates in UTC (the Z suffix or +00:00) eliminates timezone math on the server and makes the conversion to local time the client's responsibility. Never send a timestamp like 2025-06-07T14:30:00 without a timezone — the consumer has no way to know whether that is their local time or the server's.
For Unix timestamps, use seconds (not milliseconds) by convention for server-side APIs. JavaScript's Date.now() returns milliseconds, but Unix timestamp conventions and most databases use seconds. Document your choice explicitly. If your API mixes seconds and milliseconds across endpoints, debugging authentication token expiry becomes unnecessarily difficult.
Structural Mistakes That Cause Problems
Deeply nested objects are hard to query and change. An object with six levels of nesting is difficult for consumers to navigate and makes partial updates painful. Flatten where possible. If you find yourself writing response.data.user.profile.settings.preferences.theme, that structure needs refactoring.
Returning different shapes from the same endpoint based on input is an anti-pattern. If GET /users returns { name } for some users and { firstName, lastName } for others depending on creation date, every consumer must handle both shapes. Stable, consistent response shapes make caching, logging, and client code dramatically simpler.
Including computed fields alongside raw data adds value. If you store a Unix timestamp, also return the ISO 8601 formatted string. If you store a price in cents, also return the formatted currency string. This reduces client-side computation and ensures consistent formatting across all consumers of the API.
Good JSON API design is less about cleverness and more about consistency and predictability. An API that always returns the same shape, uses one naming convention, handles null intentionally, and formats dates unambiguously becomes invisible — developers can focus on building features instead of parsing defensive code. A JSON formatter helps you spot structural issues, validate syntax, and inspect deeply nested responses during development, which is where most conventions get established or violated.