Mixed casing in API response fields — userId alongside created_at in the same response object — forces every consumer to handle two naming conventions simultaneously. This is the classic sign of database column names leaking directly into the API layer without a serialization pass. It creates client-side bugs when consumers assume one convention and get the other, and it makes the API feel unfinished. iso-25010:2011 maintainability.modifiability is the direct impact: every client integration must special-case the inconsistency.
High because mixed field naming forces every API consumer to write defensive handling code, and the inconsistency compounds across every new endpoint added.
Pick one casing convention and enforce it with a serialization layer that transforms database field names before they leave the API. Add a transformer function in your handler files:
// Before -- mixed casing leaking from database:
{
userId: row.user_id,
created_at: row.created_at, // forgot to transform
firstName: row.first_name
}
// After -- consistent camelCase via transformer:
function toUserResponse(row) {
return {
userId: row.user_id,
createdAt: row.created_at,
firstName: row.first_name
}
}
For larger codebases, use camelcase-keys or a serialization framework that enforces the convention globally.
ID: api-design.naming-conventions.field-naming
Severity: high
What to look for: Examine response body field names across all endpoints. Check whether the API consistently uses one casing convention: camelCase (JavaScript convention), snake_case (Python/Ruby convention), or PascalCase (C#/.NET convention). Compare fields across at least 3 different endpoints. Also check that the chosen convention matches the ecosystem -- JavaScript/TypeScript APIs typically use camelCase, Python APIs typically use snake_case. Look for mixing within a single response (e.g., { userId: 1, created_at: "..." }).
Pass criteria: List all response field names across at least 3 endpoints and classify each as camelCase, snake_case, or PascalCase. All response field names across all endpoints must use one consistent casing convention. No mixing of camelCase and snake_case within or across responses. Do not pass when a single response mixes conventions (e.g., userId and created_at in the same object).
Fail criteria: Mixed casing conventions found across endpoints (some return camelCase, others snake_case), or within a single response object. Field names from the database layer leak through without transformation (e.g., { userId: row.user_id, created_at: row.created_at }). Quote the actual field names found in each convention.
Skip (N/A) when: Fewer than 2 API endpoints return JSON response bodies. Also skip for gRPC (Protobuf enforces snake_case in .proto files and auto-converts per language).
Detail on fail: Identify the inconsistency with examples (e.g., "User endpoint returns camelCase (userId, firstName) but order endpoint returns snake_case (order_id, created_at). 3 of 8 endpoints use snake_case while the rest use camelCase."). Max 500 chars.
Remediation: Pick one casing convention and enforce it everywhere. Use a serialization layer to transform database field names before they reach the API response.
// Before -- mixed casing leaking from database:
{
userId: row.user_id,
created_at: row.created_at, // forgot to transform
firstName: row.first_name
}
// After -- consistent camelCase with a transformer:
function toCamelCase(row) {
return {
userId: row.user_id,
createdAt: row.created_at,
firstName: row.first_name
}
}
For larger APIs, use a library like camelcase-keys or a serialization framework that handles this automatically.