About Case Converter
Naming conventions are not interchangeable decoration - each ecosystem has one, and crossing a boundary without converting is a common source of quietly missing data. camelCase is the JavaScript, Java and Swift convention; snake_case belongs to Python, Ruby, Rust and most SQL databases; kebab-case appears in URLs, CSS properties, HTML attributes and CLI flags; PascalCase names types and classes almost everywhere; and SCREAMING_SNAKE_CASE is for constants and environment variables.
The place this actually bites is the API boundary between a JavaScript client and a Python or Rails backend. A field the server calls created_at arrives at a client expecting createdAt, and because JSON access to a missing key yields undefined rather than an error, the value is simply absent - no exception, no log line, just an empty field in the UI.
Conversion is harder than splitting on a delimiter, because acronyms break the naive rules. Converting HTTPResponse or parseJSONData to snake_case requires knowing that a run of capitals is one word: the correct results are http_response and parse_json_data, not h_t_t_p_response. Round-tripping is also lossy - snake_case to camelCase to snake_case turns user_ID into user_id, so conversion is not always reversible.
For database work there is a further trap: unquoted identifiers in PostgreSQL are folded to lowercase, so a column created as "createdAt" must be quoted every time it is referenced or it silently becomes createdat and the query fails. That is the practical reason SQL conventions settled on snake_case.
Conversion runs in your browser and nothing is transmitted.
How to use the Case Converter
- Paste an identifier, a list of them, or a whole block of text.
- Pick the target convention - the tool shows every form at once so you can compare.
- Check how acronyms were handled: HTTPResponse should become http_response, not h_t_t_p_response.
- Copy the result. If you are converting API field names, convert at one boundary consistently rather than in scattered places.
Examples
-
snake_case input
user_first_name -
Title input
Convert This Sentence
Case Converter in code
The same operation this tool performs, in the languages you are most likely to need it.
// Split an identifier into words, handling acronym runs correctly
const words = (s) =>
s
.replace(/([a-z0-9])([A-Z])/g, "$1 $2") // fooBar -> foo Bar
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2") // HTTPResponse -> HTTP Response
.replace(/[_\-\s]+/g, " ")
.trim()
.toLowerCase()
.split(" ");
const snake = (s) => words(s).join("_");
const kebab = (s) => words(s).join("-");
const camel = (s) => words(s).map((w, i) => i ? w[0].toUpperCase() + w.slice(1) : w).join("");
const pascal = (s) => words(s).map((w) => w[0].toUpperCase() + w.slice(1)).join("");
snake("HTTPResponse"); // "http_response" (not h_t_t_p_response)
camel("created_at"); // "createdAt"
kebab("parseJSONData"); // "parse-json-data"
// Recursively convert keys - do this once, in your API client,
// not scattered through your components.
const convertKeys = (value, fn) => {
if (Array.isArray(value)) return value.map((v) => convertKeys(v, fn));
if (value === null || typeof value !== "object") return value;
return Object.fromEntries(
Object.entries(value).map(([k, v]) => [fn(k), convertKeys(v, fn)])
);
};
const fromApi = (data) => convertKeys(data, camel);
const toApi = (data) => convertKeys(data, snake);
// Careful: this will also rewrite keys that are DATA rather than field
// names - a map keyed by user id or locale code, for instance. Skip
// those subtrees explicitly.
import re
def snake(s: str) -> str:
s = re.sub(r"([A-Z]+)([A-Z][a-z])", r"\1_\2", s) # HTTPResponse
s = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s) # fooBar
return s.replace("-", "_").replace(" ", "_").lower()
def camel(s: str) -> str:
head, *rest = snake(s).split("_")
return head + "".join(w.title() for w in rest)
snake("HTTPResponse") # 'http_response'
camel("created_at") # 'createdAt'
# Pydantic can do it declaratively at the boundary
from pydantic import BaseModel, ConfigDict
from pydantic.alias_generators import to_camel
class User(BaseModel):
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
created_at: str # serialises as "createdAt"
-- PostgreSQL folds unquoted identifiers to lowercase
CREATE TABLE users ("createdAt" timestamptz);
SELECT createdAt FROM users; -- ERROR: column "createdat" does not exist
SELECT "createdAt" FROM users; -- works, but needs quoting forever
-- Which is why the convention is snake_case:
CREATE TABLE users (created_at timestamptz);
SELECT created_at FROM users; -- no quoting needed, case-insensitive
When you need this
- Converting API field names between a snake_case backend and a camelCase client.
- Renaming database columns to match a SQL naming convention.
- Turning a title into a kebab-case URL slug.
- Generating SCREAMING_SNAKE_CASE environment variable names from config keys.
- Normalising inconsistent identifiers across a codebase before a refactor.
Common problems and what causes them
- Acronyms mangled by a naive converter
- Splitting on every capital turns HTTPResponse into h_t_t_p_response. A correct converter treats a run of capitals followed by a lowercase letter as a word boundary - see the two-regex approach above.
- Silent data loss at the API boundary
- A client reading createdAt from a payload containing created_at gets undefined, not an error. Nothing throws, nothing logs, and the field is just empty in the UI. Convert once at the boundary, in the API client, rather than hoping every call site remembers.
- Converting keys that are data, not field names
- A recursive key converter will happily rewrite a map keyed by user id, locale code or feature flag name. Those keys are values and must not be transformed. Exclude those subtrees explicitly.
- Assuming conversion round-trips
- user_ID to camelCase and back gives user_id. The original capitalisation is not recoverable, so a pipeline that converts in both directions will not reproduce the input exactly.
- Quoted mixed-case identifiers in PostgreSQL
- Unquoted identifiers are folded to lowercase, so a "createdAt" column must be quoted in every single query or PostgreSQL looks for createdat and fails. This is the practical reason SQL settled on snake_case.
- Numbers and separators at boundaries
- Converters disagree about oauth2Token and address_line_1 - you may get oauth_2_token or oauth2_token depending on the implementation. Pick one library and use it everywhere rather than mixing.
FAQ
- Which naming convention should I use where?
- camelCase for JavaScript, Java and Swift variables; snake_case for Python, Ruby, Rust and SQL; PascalCase for types and classes in nearly all languages; kebab-case for URLs, CSS properties and CLI flags; SCREAMING_SNAKE_CASE for constants and environment variables. Follow the host ecosystem rather than a personal preference.
- How should I handle acronyms?
- Treat a run of capitals as one word: HTTPResponse becomes http_response, and parseJSONData becomes parse_json_data. Some style guides go further and capitalise only the first letter of an acronym (HttpResponse) precisely to avoid the ambiguity.
- Should I convert API field names between conventions?
- Do it in one place - the API client or a serialisation layer - rather than at every call site. Converting nowhere is also a legitimate choice: many teams simply use snake_case in JSON regardless of client language, which is less elegant and considerably less error-prone.
- Why does SQL use snake_case?
- Because unquoted identifiers are case-folded - lowercase in PostgreSQL, uppercase in Oracle - so a mixed-case column name has to be quoted in every query that touches it. snake_case sidesteps the problem entirely.
- What is the difference between camelCase and PascalCase?
- Only the first letter. camelCase starts lowercase (userName) and PascalCase starts uppercase (UserName). Most languages use the first for variables and functions, the second for types and classes.
- Does it handle acronyms like 'userID' correctly?
- Consecutive capitals are treated as a single word boundary (so 'userID' splits into 'user' and 'id'), which matches how most style guides treat acronyms - though very unusual mixed-case input may need a manual tweak.