I have a FastAPI app that uses SQLAlchemy to deal with the DB and Pydantic to deal with models.
I have two custom ORM Model defined as follows:
class A(BaseORMModel):
....
property
def categories(self) -> set:
return {
obj.b # b is a object of type B (another BaseOrmModel subclass)
for obj in self.objs
}
class B(BaseORMModel):
...
type: str
I wanted to define a pydantic schema for A then this is what I did:
class ASchema(BaseModel):
...
categories: list[str]
@field_serializer("categories")
def serialize_categories(self, categories, _info):
return ["t1", "t2"]
I would say my intention is pretty straightforward, during the serialization, I want that categories that is a list of objects in the SQLAlchemy model is managed as a list of strings in the JSON representation during a serialization, and to do that I defined a custom serializer. Unfortunately, my custom serializer is totally ignored and FastAPI returns this error
{'type': 'string_type', 'loc': ('response', 1, 'categories', 0), 'msg': 'Input should be a valid string', 'input': <app.models.category.Category object at 0x114be5d10>
You need to use field_validator
instead of field_serializer
.
field_serializer
is used when you call model_dump
, but you need to create the instance of your pydantic model first. And this is when the field_validator
works.
from pydantic import BaseModel, field_validator
class ASchema(BaseModel):
categories: list[str]
@field_validator("categories", mode="before")
@classmethod
def serialize_categories(cls, categories):
return [str(cat) for cat in categories]
a = ASchema.model_validate({"categories": [{"q"}, [1,]]})
print(a.model_dump())
Output:
'categories': ["{'q'}", '[1]']}