CamelCase Models with FastAPI and Pydantic
The easiest way to to have camel-case JSON request/response body while keeping your models snake-cased
Intro
It took me a while to figure out how to use camel-casing for one of the Fast API micro-services endpoints that I have been working on while keeping “Model” fields snake-cased.
The documentation for FastAPI and Pydantic are awesome but it did not cover that part in a nice and easy example to comprehend . This is why I decided to create this tutorial.
I have also created a package called fastapi_camelcase
which you can install using pip
and use right away, I wrote an article about it here.
HINT: This tutorial assumes that you have some experience with FAST API and know how to create REST endpoints using Pydantic models
The Problem
lets assume that you have the following application exposing an API endpoint that represent a resource called “User” in your “models.py”
from pydantic import BaseModel
class User(BaseModel):
first_name: str
last_name: str = None
age: int
and you have your “main.py” containing the “run” configuration
import uvicorn
from fastapi import FastAPI
from models import User
app = FastAPI()
@app.post("/user/", response_model=User)
async def create_user(user: User):
return user
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
if you run the application
python main.py

we will see snake-cased request/response body in the OpenAPI documentation as we expected. Now we can change the field names to camelCase but that does not follow the PEP-8 standard.

Pydantic Aliases
Aliases for pydantic models can be used in the JSON serialization in camel case instead of snake case as follows:
from pydantic import BaseModel, Field
class User(BaseModel):
first_name: str = Field(..., alias='firstName')
last_name: str = Field(..., alias='lastName')
age: int = Field(..., alias='age')
That we make our schema in camelCase

What if we have 1000 fields instead of 3, what do we do now? I wish there was a magic alias generator.
Luckily there is :)
Alias Generator
Pyndantic has a Config class which controls the behaviour of models. We can generate aliases for all of the model fields as follows:
from pydantic import BaseModel
from humps import camelize
def to_camel(string):
return camelize(string)
class User(BaseModel):
first_name: str
last_name: str = None
age: float
class Config:
alias_generator = to_camel
now lets try it out

Internal server error? SAY WHAAAAT?

Well of course, we are using aliases (camelCase) instead of field names (snake_case), I hope there is an easy to fix that
Luckily there is :D
All what is needed to be done is to add the following to the model Config class
allow_population_by_field_name = True
so our model should look like this now
from pydantic import BaseModel
from humps import camelize
def to_camel(string):
return camelize(string)
class User(BaseModel):
first_name: str
last_name: str = None
age: float
class Config:
alias_generator = to_camel
allow_population_by_field_name = True
lets try it one last time

AND BOOM!, all of our code is in snake_case and request/response and documentation are in camelCase, isn’t that AWESOME?
One last enhancement
We would probably have many models used by many API endpoints and we want to use camelCase across them all, right? probably :)
Now lets use the power on inheritance
from pydantic import BaseModel
from humps import camelize
def to_camel(string):
return camelize(string)
class CamelModel(BaseModel):
class Config:
alias_generator = to_camel
allow_population_by_field_name = True
class User(CamelModel):
first_name: str
last_name: str = None
age: int
Great, now you can inherit from CamelModel
instead of BaseModel
and ENJOY!!!
I created a simple package easy to use following the above tutorial.
pip install fastapi_camelcase
from fastapi_camelcase import CamelModelclass User(CamelModel):
first_name: str
last_name: str = None
age: int
The full code for this example can be found here on github