MongoDB Binary字段转Pydantic模型遇编码及类型错误的问询
解决方案:MongoDB二进制图片字段转Pydantic模型
问题根源
- 用
bytes定义Pydantic字段时,Pydantic会默认尝试将二进制数据解码为Unicode字符串,而图片的二进制流包含非合法Unicode字符,触发UnicodeDecodeError。 - 用
bson.Binary并开启arbitrary_types_allowed时,MongoDB驱动返回的图片数据是原生bytes类型,而非bson.Binary实例,导致类型不匹配错误。
可行解决方案
1. 自定义Pydantic字段类型(推荐,通用型)
创建一个自定义字段,自动处理bytes与bson.Binary的转换,无需在查询或模型中额外处理:
from pydantic import GetCoreSchemaHandler from pydantic_core import core_schema from bson import Binary class BinaryImageField(bytes): @classmethod def __get_pydantic_core_schema__(cls, source_type, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: return core_schema.no_info_after_validator_function( cls.validate, core_schema.bytes_schema(), ) @classmethod def validate(cls, value): if isinstance(value, bytes): return Binary(value) elif isinstance(value, Binary): return value raise ValueError("字段必须为bytes或bson.Binary类型")
在Pydantic模型中使用该字段:
from pydantic import BaseModel class ImageRecord(BaseModel): id: str image: BinaryImageField class Config: arbitrary_types_allowed = True
2. 查询MongoDB时转换类型
在从MongoDB读取数据后,手动将bytes类型的图片字段转换为bson.Binary实例:
from pymongo import MongoClient from bson import Binary from your_models import ImageRecord # 连接MongoDB client = MongoClient("mongodb://localhost:27017/") db = client["your_database"] collection = db["your_collection"] # 查询并转换数据 image_records = [] for doc in collection.find(): if isinstance(doc.get("image"), bytes): doc["image"] = Binary(doc["image"]) image_records.append(ImageRecord(**doc))
3. 使用Pydantic前置验证器
通过BeforeValidator装饰器,在模型验证前自动将bytes转换为bson.Binary:
from pydantic import BaseModel, BeforeValidator from bson import Binary def convert_bytes_to_binary(value): if isinstance(value, bytes): return Binary(value) return value class ImageRecord(BaseModel): id: str image: Binary = BeforeValidator(convert_bytes_to_binary) class Config: arbitrary_types_allowed = True
额外注意事项
- 确保MongoDB中存储的图片数据是二进制类型(而非Base64字符串),否则需要调整字段处理逻辑。
- 如果使用Pydantic v1版本,自定义字段需改用
validator装饰器实现,而非__get_pydantic_core_schema__。
内容的提问来源于stack exchange,提问作者F. F.
相关产品推荐
相关产品推荐

