如何让Pydantic不将自定义Enum序列化为字典适配SQLAlchemy
解决Pydantic序列化自定义Enum为Dict导致SQLAlchemy报错的问题
问题分析
你的自定义State枚举同时继承了数据类StateDataMixin和Enum,Pydantic默认会将其序列化为数据类的字段结构(即{'state': {'state': 'Alaska', 'short': 'AK'}}),而SQLAlchemy需要接收State枚举实例才能正确存入数据库,因此触发unhashable type: 'dict'错误。
解决方案
方案1:给Pydantic模型添加自定义序列化器
在你的SomeState(或对应的ItemCreate)模型中,使用model_serializer装饰器,指定序列化时直接返回枚举实例:
class SomeState(BaseModel): state: State @model_serializer def serialize_state(self): return {"state": self.state}
调用model_dump()后,结果会是{'state': State.ALASKA},直接适配SQLAlchemy的枚举类型要求。
方案2:为State类型添加Pydantic核心模式
通过为State类实现__get_pydantic_core_schema__方法,告诉Pydantic将其当作枚举类型处理,而非数据类:
from pydantic_core import core_schema class State(StateDataMixin, Enum): ALABAMA = "Alabama", "AL" ALASKA = "Alaska", "AK" # 其他州枚举项... @property def value(self): return self._value_.state # type: ignore @classmethod def __get_pydantic_core_schema__(cls, source_type, handler): # 复用枚举的核心校验逻辑 enum_schema = handler(Enum) return core_schema.no_info_wrap_validator_function( lambda v, info: cls(v) if isinstance(v, str) else v, enum_schema, )
这个方法会让Pydantic始终将State视为枚举类型,序列化时保留实例,同时支持从字符串(如"Alaska")反序列化回枚举。
额外验证
若使用SQLAlchemy 2.0+,Mapped[State]可自动识别枚举类型,若需显式指定,可修改SQLAlchemy模型:
from sqlalchemy import Enum as SAEnum class Item(Base): __tablename__ = "items" id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] state: Mapped[State] = mapped_column(SAEnum(State))
确保SQLAlchemy明确识别该字段为枚举类型。
内容的提问来源于stack exchange,提问作者Mateusz Anikiej
相关产品推荐
相关产品推荐

