Mapping camelCase JSON to snake_case Pydantic fields
Pydantic field aliasing across the JSON boundary.
set an alias_generator (to_camel) plus populate_by_name in model config, accept aliases on input, and serialize with by_alias=True so responses come out camelCase.
WHAT THIS TESTS Whether you can bridge frontend camelCase and Pythonic snake_case cleanly using Pydantic configuration, keeping Python code idiomatic.
A GOOD ANSWER COVERS The goal is to keep snake_case attributes in Python while exposing camelCase at the JSON boundary in both directions. In Pydantic v2 you set model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True), importing to_camel from pydantic.alias_generators. The alias_generator computes a camelCase alias for every field, so incoming userName maps to user_name. populate_by_name=True (called allow_population_by_field_name in v1) lets the model also accept the original snake_case name, which is handy for internal construction and tests. For outgoing data you serialize with model_dump(by_alias=True) or model_dump_json(by_alias=True) so keys come out as camelCase. In FastAPI, declaring such a model as a response_model serializes by alias, giving camelCase responses without manual work. You can also alias individual fields with Field(alias=...) when only a few differ.
COMMON WRONG ANSWERS Renaming Python attributes to camelCase, violating PEP 8 and spreading non-idiomatic names through the codebase. Writing a manual dict-comprehension mapper for every field. Aliasing only the input and forgetting by_alias on output, so responses revert to snake_case. Forgetting populate_by_name, which then blocks constructing the model by its real field names.
LIKELY FOLLOW-UPS What is the difference between alias, validation_alias, and serialization_alias in v2? How does this interact with response_model_by_alias? How do you handle a few irregular field names?
ONE CONCRETE EXAMPLE class UserDTO(BaseModel): user_name: str; model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True). Then UserDTO.model_validate({'userName': 'ada'}) sets user_name='ada', and user.model_dump(by_alias=True) returns {'userName': 'ada'}. The Python code keeps using user.user_name throughout.
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.