camelCase to snake_case Converter
JavaScript and TypeScript use camelCase for variable names1; Python, SQL, and most configuration formats use snake_case2. When you move data between these ecosystems (writing a Django model from a TypeScript interface or mapping a REST response to a database column), you need to rename every field.
Where camelCase and snake_case are used
JavaScript and TypeScript use camelCase for all variable and function names; Python, PostgreSQL, and most ORM frameworks use snake_case2. REST APIs built with Python (FastAPI, Django REST Framework) return snake_case JSON fields by default3. Consequently, every JavaScript frontend that consumes a Python API has a casing mismatch to resolve. TypeScript interfaces must match the actual field names from the response, so those interface properties need to be snake_case when the backend sends them that way, or a mapping layer must convert them. Ruby and Rust also default to snake_case for function and variable names, which means the camelCase-to-snake_case conversion is relevant far beyond the JavaScript-Python boundary. Environment variables in Docker Compose and CI pipelines use SCREAMING_SNAKE_CASE, the uppercase variant, making this conversion the first step before applying uppercase transformation.
Edge cases: acronyms, numbers, and mixed inputs
Acronyms split on every capital letter transition: "userID" becomes "user_i_d" and "parseHTML" becomes "parse_h_t_m_l". For cleaner results with acronyms, use lowercase forms in the source: "userId" → "user_id" and "parseHtml" → "parse_html". Numbers act as word boundaries: "address2" becomes "address_2" and "h1Tag" becomes "h_1_tag". Mixed inputs with existing underscores or hyphens also split correctly: "phone-number" and "phone_number" both produce "phone_number". Consecutive uppercase letters that form an acronym without lowercase separation, like "IOStream", produce individual splits for each letter: "i_o_stream". When your source identifiers follow the Microsoft C# convention of PascalCase with two-letter acronyms in uppercase ("IOStream"), consider normalizing to "IoStream" before conversion for a cleaner result. Empty lines in a multi-line paste pass through unchanged, so blank separators between groups of fields do not produce unwanted underscores.
Workflow: converting a TypeScript interface to a Python dataclass
Building on this, here is the exact workflow. Copy your TypeScript interface property names (just the names, one per line). Paste them in and convert a whole interface to snake_case in a single step, then copy the output and use those names as your Python dataclass attributes. The tool processes each line independently, so a 20-field interface converts in one pass. You then annotate the types in Python and the mapping is complete. For Pydantic v2 models, the snake_case attribute names map directly to JSON field names by default, which means your Python model and the TypeScript interface share the same vocabulary through the API contract. When the backend adds a new field, you convert the new name, append it to the dataclass, and the integration stays in sync without a manual find-and-replace across multiple files.
Enforcing naming conventions at the JavaScript-Python boundary with linters
Naming conventions at the JavaScript-Python boundary are the most common source of undetected casing violations in full-stack codebases. Each language enforces its own convention through tooling, but neither tool knows about the other side of the boundary. Adding linting rules on both sides closes that gap before a mismatch reaches code review. When a Python backend adds a new snake_case field and the TypeScript frontend does not update its interface, the mismatch passes silently through local development and only surfaces in production when a component reads an undefined property.
ESLint camelcase rule for JavaScript and TypeScript projects
ESLint's built-in camelcase rule flags any variable or property name that is not camelCase.4 When your TypeScript frontend receives a Python API response and assigns snake_case fields directly to variables, ESLint catches the violation. Configure the rule with "allow": [] to reject all exceptions, or add specific field names to the allow list for cases where you deliberately keep the raw API name.
Configuring this rule early saves time during code review. When the camelcase rule is active, a developer who pastes a raw snake_case field from a Python response sees the error immediately in the editor rather than shipping a silent mismatch. You can verify your setup in CapyToolkit by pasting a converted field list and comparing it against the original, which makes the casing boundary visible before the code ever reaches a linter. The @typescript-eslint/naming-convention rule provides finer control and can enforce camelCase on all variable, parameter, and property selectors simultaneously in one rule configuration.5
pep8-naming plugin for Python CI
The pep8-naming package extends flake8 with naming checks: N801 for PascalCase class names, N802 for lowercase function names, and N803 for lowercase argument names.6 Adding it to your [flake8] or [tool.flake8] configuration in setup.cfg or pyproject.toml ensures every snake_case violation produces a CI failure. Run pip install pep8-naming and flake8 with the N rule selected to see only naming violations without other style warnings from unrelated rules.
Pydantic alias_generator: accepting camelCase POST bodies in Python APIs
Pydantic v2 provides a clean mechanism for accepting camelCase JSON in a Python API while keeping snake_case model attributes internally. Understanding how to configure it prevents the common pattern of writing a manual field aliasing function for every model. The same alias configuration also simplifies testing because your test code can send camelCase request bodies that match what the real frontend sends, which means your integration tests exercise the exact same serialization path as production traffic.
Setting model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True) in a Pydantic v2 model imports to_camel from pydantic.alias_generators and generates camelCase aliases for all snake_case fields automatically.7 Your FastAPI route then accepts {"userId": 123} as a POST body and maps it to user_id on the Python model without any manual alias declarations. The populate_by_name=True setting ensures you can still initialize the model with snake_case names in your own Python code.
Verifying the alias configuration in FastAPI docs
FastAPI generates an OpenAPI schema from your Pydantic models automatically. When you add alias_generator=to_camel, the schema at /docs shows camelCase property names in the request body editor. Run the dev server, open /docs, expand your POST route, click "Try it out", and confirm the example JSON uses camelCase. If it shows snake_case instead, the alias_generator is not applied yet. This visual check catches misconfiguration before integration tests do.
When to use this
Use this when migrating a TypeScript interface or JavaScript object to a Python data class, SQLAlchemy model, or any system that follows snake_case conventions.
Examples
TypeScript interface → Python dataclass field names
userId firstName lastName createdAt isEmailVerified
user_id first_name last_name created_at is_email_verified
JSON API response → SQL column names
orderId shippingAddress totalAmount
order_id shipping_address total_amount
- 1.
Google, "Google JavaScript Style Guide," google.github.io, accessed June 2026. https://google.github.io/styleguide/jsguide.html#naming
- 2.
Guido van Rossum et al., "PEP 8 – Style Guide for Python Code," peps.python.org, accessed June 2026. https://peps.python.org/pep-0008/#function-and-variable-names
- 3.
PostgreSQL Global Development Group, "PostgreSQL: Documentation: 18: 4.1. Lexical Structure," postgresql.org, June 2026. https://www.postgresql.org/docs/current/sql-syntax-lexical.html
- 4.
ESLint, "camelcase," eslint.org, accessed June 2026. https://eslint.org/docs/latest/rules/camelcase
- 5.
typescript-eslint, "@typescript-eslint/naming-convention," typescript-eslint.io, accessed June 2026. https://typescript-eslint.io/rules/naming-convention
- 6.
PyCQA, "pep8-naming: Naming Convention checker for Python," github.com, accessed June 2026. https://github.com/PyCQA/pep8-naming
- 7.
Pydantic, "Alias," pydantic.dev, accessed June 2026. https://pydantic.dev/docs/validation/latest/concepts/alias/