JSON Best Practices for Developers
Battle-tested tips and best practices for working with JSON in APIs, config files, and data exchange from years of production experience.
Keep JSON readable for humans (it matters more than you think)
Readable JSON isn't just about aesthetics — it's about developer productivity and reducing bugs. I've debugged too many issues that started with someone misreading a wall of minified JSON.
**Use consistent indentation**: 2 spaces is the most common convention across the JavaScript/Node ecosystem, and it works well with most tools. Pick one style and stick with it — don't mix tabs and spaces, don't switch between 2 and 4 spaces randomly.
**Give keys meaningful, specific names**: Use `user_id` not just `id` when the context matters. Use `customer_email` instead of just `email`. When you're looking at nested data, the extra clarity helps.
**Use arrays for ordered lists, objects for key-value pairs**: This might sound obvious, but I see it get mixed up. Arrays are for collections of similar items where order matters. Objects are for named properties.
**Include versioning early**: APIs should version their JSON format from day one. A simple pattern is `{"version": "1.0", "data": {}}` or including the version in the URL path like `/api/v1/orders`.
**Use consistent date and time formats**: ISO 8601 is the standard — `2026-06-20T14:30:00Z` (the trailing Z means UTC). Always send dates as strings in ISO format, never as timestamps unless you have a very good reason. And always use UTC when you can.
**Use consistent boolean names**: Prefer `active`, `enabled`, `verified` over `isActive`, `isEnabled`, `isVerified` — they read cleaner in JSON and are just as clear. But consistency matters more than the exact choice.
Remember: Someone will need to read this JSON later. That someone might be future you at 2 AM trying to debug a production issue. Make their (your) life easier.
Keep JSON efficient for machines (balance is key)
While human readability is important, machine efficiency matters too — especially at scale. The good news is you don't have to choose one over the other if you're smart about it.
**Minify before sending over the network**: Remove all unnecessary whitespace when sending JSON over HTTP. Most web frameworks will do this automatically for you, but double-check.
**Don't include unnecessary fields**: Only send what the consumer actually needs. If your frontend never uses the `updated_at` field, don't send it. This reduces payload size and makes responses faster.
**Use arrays of objects for lists, not objects with numeric keys**: `[{"id": 1}, {"id": 2}]` is much better than `{"1": {"id": 1}, "2": {"id": 2}}`. Arrays are easier to iterate over and play nicer with type systems.
**Consider compression**: Gzip or Brotli compression can drastically reduce payload sizes (often by 70-80%). Make sure your server is configured to compress JSON responses.
**Avoid deeply nested structures**: While JSON supports arbitrary nesting, deeply nested structures (5+ levels) can be hard to work with. If you find yourself with `user.order.items.product.vendor.address`, consider flattening or paginating.
**Be consistent with null vs missing fields**: Decide whether missing fields are semantically the same as `null`, and document that decision. I prefer explicit `null` values for optional fields that are known to exist but have no value, and omitting fields that are truly optional.
**Balance readability with efficiency**: Here's the approach that works for most teams: keep your source files and development environments using formatted JSON, but send minified JSON in production. This gives you the best of both worlds — easy debugging in development, efficient payloads in production.
Common pitfalls to avoid (I've made all these mistakes)
After working with JSON in production for years, these are the pitfalls I see most often — and the ones that have caused me the most pain:
**Don't use JSON for binary data**: Binary data doesn't belong directly in JSON. If you must include it, use Base64 encoding, but be aware that Base64 increases the size by about 33%. Even better: use a separate file or blob storage with a URL reference.
**Don't put large amounts of HTML in JSON strings**: If you find yourself putting entire HTML pages in JSON fields, you might want to reconsider your architecture. Store templates separately, or send structured data that the client can render.
**Don't use nested structures more than 3-4 levels deep**: Deeply nested JSON is hard to work with in frontend code, hard to document, and hard to change without breaking things. Flatten when you can.
**Don't change the structure without versioning**: API changes should be versioned. Never change the structure of a response in a breaking way without bumping the version. If you rename `name` to `fullName`, your users will experience downtime.
**Don't rely on object key order**: Even though many modern parsers preserve insertion order, it's not part of the JSON spec and you shouldn't depend on it. Use arrays if order matters.
**Don't put sensitive data in JSON that gets logged**: If you log API requests or responses, make sure you redact sensitive fields like passwords, API keys, credit card numbers, and PII. I've seen way too many production logs with plaintext passwords.
**Don't use JSON as a hammer for every nail**: JSON is great, but it's not the right tool for everything. For configuration files where you want comments, use YAML. For large datasets with complex queries, use a database. For high-performance binary data, use Protocol Buffers or MessagePack.
Practical checklist for production JSON APIs
This is the checklist I wish I had when I was building my first JSON API. I now use something like this for every API I work on:
**1. Validate all incoming JSON before processing it**: Never trust data from the client. Validate every field with a schema. I recommend Zod, Joi, or JSON Schema. Don't just parse — validate.
**2. Return consistent error formats**: Every error response should have the same shape. I use something like: `{"error": {"message": "Invalid payload", "code": "VALIDATION_ERROR", "details": []}}`. Consistency makes handling errors on the frontend much easier.
**3. Use appropriate HTTP status codes**: 200 OK for successful GETs, 201 Created for successful POSTs, 204 No Content for successful DELETEs, 400 Bad Request for invalid input, 401 Unauthorized for missing auth, 403 Forbidden for insufficient permissions, 404 Not Found for missing resources, 500 Internal Server Error for server-side issues. Don't return 200 OK for everything with an error in the body.
**4. Set the correct Content-Type header**: Always return `Content-Type: application/json`. I've seen bugs where responses were interpreted as text/html because the header was missing.
**5. Pretty-print by default in development, minify in production**: Make debugging easy in development, but optimize for performance in production.
**6. Document your JSON schema somewhere developers can find it**: Use OpenAPI/Swagger, JSON Schema, or just good old-fashioned Markdown. If you don't document the shape, developers will guess, and they'll guess wrong.
**7. Include pagination for list endpoints**: Don't return thousands of items in one response. Use `limit` and `offset` or cursor-based pagination. I prefer cursor-based for most use cases because it handles real-time data better.
**8. Handle CORS properly**: Set up CORS headers correctly so browsers can call your API. Don't use `Access-Control-Allow-Origin: *` in production unless your API is truly public and intended to be called from any origin.
**9. Rate limit your API**: Protect your API from abuse with rate limiting. Return `429 Too Many Requests` when limits are exceeded, and include headers with rate limit info.
**10. Include request IDs**: Generate a unique ID for each request and return it in the headers (like `X-Request-ID`). This makes debugging production issues much easier — you can trace a request through logs end-to-end.
Testing and debugging JSON effectively
Good testing practices will save you from countless JSON-related bugs. Here's what I've learned:
**Write contract tests**: Test that your API returns the exact shape of JSON you expect. If you change the shape accidentally, your tests will catch it before users do.
**Use snapshot testing carefully**: Snapshot tests can be useful, but they can also become noise if you update them too often without reviewing. Use them for stable parts of your API, not for parts that change frequently.
**Test edge cases**: What if a string is empty? What if a number is zero? What if a field is `null`? What if the array is empty? Test all these cases.
**Use tools to inspect JSON**: In the browser, the Network tab's pretty-print feature is invaluable. On the command line, `jq` is indispensable. In VS Code, the built-in JSON support is excellent.
**Log intelligently**: Log request IDs, but don't log entire payloads with sensitive data. Log what you need for debugging, but no more.
**Save examples**: Keep a collection of known-good JSON payloads in your repo or documentation. When something breaks, you have something to compare against.
**Fuzz your API**: If you're feeling ambitious, use fuzz testing to send random JSON to your API and see if it breaks. This can uncover edge cases you never thought of.
Security considerations for JSON
JSON is data, and data can be dangerous. Here are the security considerations you need to keep in mind:
**Never parse JSON with eval()**: This should go without saying, but I've seen it done. Always use `JSON.parse()` or a proper JSON library. Using `eval()` is a huge security risk.
**Be careful with large JSON payloads**: Large payloads can cause denial-of-service issues. Set reasonable limits on request size. Most web frameworks let you configure this.
**Validate, validate, validate**: Every piece of incoming JSON should be validated against a schema. Don't just parse and use — validate first. This prevents a whole class of injection attacks and invalid data issues.
**Beware of JSON hijacking**: While modern browsers have mostly fixed this, it's still worth understanding. The main defense is to always return JSON objects at the top level, not arrays, and to use proper CSRF protection.
**Redact sensitive data**: When logging or storing JSON, redact sensitive fields like passwords, tokens, credit card numbers, and PII. You don't want this data in your logs or your database backups.
**Use HTTPS**: Always serve JSON APIs over HTTPS. This prevents man-in-the-middle attacks and ensures the integrity of your data in transit.
**Be careful with user-generated JSON**: If users can submit arbitrary JSON, be extra careful. Validate rigorously, sanitize when necessary, and never trust that the structure is what you expect.
Try These Tools
Open the tools that go with this tutorial and practice what you learned.
JSON Formatter
Format JSON with clean indentation so logs, payloads, and fixtures are easier to read.
JSON Validator
Check JSON syntax and catch parser errors before the payload goes any further.
JSON Minify
Strip whitespace from JSON when you need a compact payload.
More Tutorials in This Category
Learn how to format JSON for readability, common use cases, and step-by-step examples with real-world scenarios.
Learn how to validate JSON, common errors to look for, and practical examples from real-world development.
Keep Learning
How to Compare Two JSON Documents Effectively
Learn how to compare JSON files, spot differences, and understand what changed with real-world debugging workflows.
How to Decode a JWT: A Comprehensive Step-by-Step Tutorial
Learn what a JWT is, how to decode one, what each part means, and real-world debugging tips from production experience.