fastapipydanticpydantic-v2

Pydantic v2 custom field serializer seems to be ignored


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>

Solution

  • 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]']}