Converting Cases Across Programming Languages: A Practical Reference
Why Case Conversion Matters
Different contexts demand different naming conventions. An API returns snake_case keys, but your TypeScript codebase uses camelCase. A database column is created_at, but your Java model needs createdAt. A CLI flag is --max-retries, but your Python variable is max_retries.
Case conversion bridges these boundaries. Doing it correctly — handling abbreviations, acronyms, and edge cases — separates robust code from fragile string manipulation.
Case Types at a Glance
| Case | Pattern | Example | Typical Use |
|---|---|---|---|
| camelCase | firstWordLower, restUpper | getUserById | JS/TS variables, functions |
| PascalCase | everyWordUpper | UserService | Classes, types, components |
| snake_case | all_lower_with_underscores | user_name | Python, Ruby, database columns |
| SCREAMING_SNAKE | ALL_UPPER_WITH_UNDERSCORES | MAX_RETRIES | Constants |
| kebab-case | all-lower-with-hyphens | content-type | URLs, CLI flags, HTTP headers |
| UPPER_KEBAB | ALL-UPPER-WITH-HYPHENS | CONTENT-TYPE | HTTP headers (alternative) |
JavaScript / TypeScript
Using Lodash
import { camelCase, snakeCase, kebabCase, upperFirst } from 'lodash'
camelCase('user_name') // 'userName'
snakeCase('userName') // 'user_name'
kebabCase('userName') // 'user-name'
upperFirst(camelCase('user_name')) // 'UserName' (PascalCase)
Manual Conversion
// camelCase to snake_case
function toSnakeCase(str) {
return str
.replace(/([A-Z])/g, '_$1')
.toLowerCase()
.replace(/^_/, '')
}
// snake_case to camelCase
function toCamelCase(str) {
return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase())
}
// Any case to PascalCase
function toPascalCase(str) {
return str
.replace(/([_-][a-z])/g, (_, c) => c.slice(1).toUpperCase())
.replace(/^[a-z]/, c => c.toUpperCase())
}
Transforming Object Keys
A common use case: converting API response keys from snake_case to camelCase:
function transformKeys(obj) {
if (Array.isArray(obj)) return obj.map(transformKeys)
if (obj !== null && typeof obj === 'object') {
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [
toCamelCase(key),
transformKeys(value)
])
)
}
return obj
}
Python
Built-in (Limited)
# Only handles a few conversions
'userName'.replace('_', '-').lower() # not general-purpose
Using inflection
import inflection
inflection.camelize('user_name') # 'UserName' (PascalCase)
inflection.camelize('user_name', False) # 'userName' (camelCase)
inflection.underscore('UserName') # 'user_name' (snake_case)
inflection.dasherize('user_name') # 'user-name' (kebab-case)
Using pydantic
Pydantic models support automatic alias generation:
from pydantic import BaseModel, ConfigDict
class User(BaseModel):
model_config = ConfigDict(alias_generator=lambda x: inflection.camelize(x, False))
first_name: str
last_name: str
# Accepts camelCase input, uses snake_case internally
user = User.model_validate({'firstName': 'Alice', 'lastName': 'Smith'})
user.first_name # 'Alice'
Java
Using Jackson
Jackson can map between naming conventions during serialization:
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class User {
private String firstName;
private String lastName;
}
// Serializes as: {"first_name": "Alice", "last_name": "Smith"}
Available strategies:
| Strategy | Converts to |
|---|---|
SnakeCaseStrategy | first_name |
UpperCamelCaseStrategy | FirstName |
KebabCaseStrategy | first-name |
LowerDotCaseStrategy | first.name |
Using Guava
import com.google.common.base.CaseFormat;
CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "firstName"); // "first_name"
CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "first_name"); // "FirstName"
CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, "firstName"); // "first-name"
Go
Using strcase
import "github.com/iancoleman/strcase"
strcase.ToCamel("user_name") // "UserName" (PascalCase)
strcase.ToLowerCamel("user_name") // "userName" (camelCase)
strcase.ToSnake("userName") // "user_name"
strcase.ToKebab("userName") // "user-name"
Using struct tags
Go's JSON and YAML tags handle naming convention mapping:
type User struct {
FirstName string `json:"first_name" yaml:"first-name"`
LastName string `json:"last_name" yaml:"last-name"`
}
Edge Cases to Handle
| Input | camelCase | snake_case | kebab-case | Pitfall |
|---|---|---|---|---|
XMLParser | xmlParser | xml_parser | xml-parser | Acronym splitting |
getUserID | — | get_user_id | get-user-id | Consecutive uppercase |
HTTPSConnection | httpsConnection | https_connection | https-connection | Acronym at start |
already_snake | alreadySnake | — | already-snake | Double underscore |
3dModel | 3dModel | 3d_model | 3d-model | Leading digit |
No library handles all edge cases perfectly. Test against your actual data, especially names with acronyms and numbers.
Key Takeaways
- Case conversion is essential at API boundaries, database mappings, and framework integrations
- Lodash (JS), inflection (Python), Guava (Java), and strcase (Go) handle common conversions
- Object key transformation is the most frequent use case — build a recursive transformer once and reuse it
- Acronyms and consecutive uppercase letters are the hardest edge cases — test against real data
- Prefer library solutions over regex for production code; they handle more edge cases
- Use framework features (Pydantic aliases, Jackson naming strategies, Go struct tags) when available
Related Guides
Try It Yourself
Convert text between any naming convention instantly with our free Case Converter. Paste any string and see conversions across camelCase, PascalCase, snake_case, kebab-case, and more.