JSON Key Naming Conventions: camelCase vs snake_case
Content owner: · Reviewed and updated: August 9, 2026 · Review standards
JSON permits both {"userId": 5} and {"user_id": 5}. For a new public API, choose camelCase when the published contract and primary clients already use lower camel case; choose snake_case when that is the established wire-format convention. Do not expose one style and silently alternate later: key names are case-sensitive contract fields, and consistency is more important than mirroring a server's internal variable names.
The Two Main Contenders
Almost every JSON API in the wild picks one of two conventions for keys: camelCase (firstName, createdAt) or snake_case (first_name, created_at). A handful use kebab-case (first-name), but this is rare because the hyphen makes the key awkward to access in many languages without bracket notation.
Same response, three styles:
camelCase:
{"firstName": "Ana", "createdAt": "2025-01-15"}
snake_case:
{"first_name": "Ana", "created_at": "2025-01-15"}
kebab-case:
{"first-name": "Ana", "created-at": "2025-01-15"}
The Case for camelCase
camelCase works naturally with JavaScript and TypeScript property access: response.firstName. It is also the required or recommended JSON field style in published Google and Microsoft API guidance. Choose it when your existing schema, generated clients, and neighboring APIs already use lower camel case.
The Case for snake_case
snake_case is a valid wire-format choice and can reduce mapping work in ecosystems that already publish underscored field names. It also keeps word boundaries visible in long names such as customer_account_holder_email. Choose it because it matches an established public contract, not merely because one current backend happens to use snake_case variables.
Decision Matrix
| Question | Prefer camelCase when | Prefer snake_case when |
|---|---|---|
| Existing contract | Neighboring fields and APIs use camelCase | Neighboring fields and APIs use snake_case |
| Generated clients | Your schema generator emits lower camel case | Your generator preserves lower snake case |
| Primary consumers | Direct JavaScript property access is the documented norm | Underscored wire fields are already documented and stable |
| Greenfield default | Your organization follows Google or Microsoft-style API guidance | Your organization has a written snake_case API standard |
The deciding artifact should be the API schema or style guide. A backend implementation can change; a public field name may need to remain compatible for years.
What About Mixing Conventions?
The worst thing you can do is mix conventions within a single API. A response that contains {"userId": 5, "first_name": "Ana"} looks like the work of three different teams who never spoke to each other. It forces every client to handle both casing styles and makes the API harder to learn.
If an existing service has inconsistent keys, first inventory the fields clients actually consume. Add aliases only where the serializer and schema can document them, announce a deprecation window, and use a new API version when removing or renaming fields would otherwise break clients. Do not return both spellings indefinitely because they can drift to different values.
Handling Translation at the Boundary
When backend and frontend models use different conventions, translate through an explicit serialization layer backed by the API schema. Test nested objects, arrays, acronyms, and collisions such as user_id plus userId. A generic recursive key converter can silently overwrite one of those fields, so conversion should fail on collisions rather than guess.
Contract-first boundary mapping:
wire.created_at → model.createdAt
wire.account_id → model.accountId
unknown or colliding key → validation error
Keep this mapping in the serializer or generated client so every caller follows the same rule.
For one-off inspection, validate the payload with our JSON Formatter, then test candidate field names with the Case Converter.
Other Rules That Apply Either Way
- Use plurals for arrays and singulars for single objects:
users,user. - Prefer full words to abbreviations.
address, notaddr. - Date keys should end in suffixes that signal type:
createdAt(ISO timestamp),createdOn(date only),createdTimestamp(Unix epoch). - Boolean keys should read as questions or assertions:
isActive,hasPaid, notactivealone (which is ambiguous). - Reject duplicate member names. RFC 8259 warns that receivers handle duplicate names inconsistently; validation should fail before a payload reaches business logic.
Frequently Asked Questions
Does JSON case-sensitivity matter?
Yes. {"User": 1} and {"user": 1} are two different keys. Always be exact about case in client code, especially when parsing JSON manually.
Is camelCase faster to parse than snake_case?
No. Parsing speed is dominated by I/O and string length, not key style. Pick based on readability and consistency, not perceived performance.
What if my consumers use multiple languages?
Keep one documented wire format and let generated clients or explicit serializers map it to language-native models. Avoid changing the JSON contract per client language.