You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Pydantic自定义编码器传递JSON_OPTIONS优化MongoDB日期序列化?

问题分析与解决方案

你用错了Pydantic的json()方法的encoder参数——这个参数接受的是JSONEncoder类,不是直接传json_util.dumps这种序列化函数。你传json_util.dumps的时候,Pydantic内部会尝试把它当作类去实例化,而且后面的json_options参数会被传给默认的JSONEncoder构造函数,自然就报“意外参数”的错了。


方案1:直接转字典后用PyMongo插入(最优)

MongoDB的驱动PyMongo本身就支持直接处理Python的datetime和ObjectId类型,根本不需要先转成JSON字符串。你只需要把Pydantic对象转成Python字典,直接丢给insert_one或者insert_many就行:

from bson import ObjectId
from datetime import datetime
import pydantic
import pymongo

class A(pydantic.BaseModel):
    w: ObjectId
    x: datetime

# 初始化MongoDB客户端
client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["test_db"]
collection = db["test_col"]

# 实例化对象并转字典插入
a = A(w=ObjectId("650000000000000000000000"), x=datetime(2023,1,1))
collection.insert_one(a.model_dump())  # 旧版Pydantic用a.dict()

这样插入后,MongoDB里的x会是标准的ISODate类型,w也会保持ObjectId类型,完全符合预期。


方案2:如果确实需要用json_util控制序列化格式

要是你非得生成特定格式的BSON/JSON字符串,别用Pydantic的json()方法,先转字典再直接调用json_util.dumps,同时传入json_options:

from bson import ObjectId, json_util
from bson.json_util import DatetimeRepresentation
from datetime import datetime
import pydantic

class A(pydantic.BaseModel):
    w: ObjectId
    x: datetime

a = A(w=ObjectId("650000000000000000000000"), x=datetime(2023,1,1))
# 配置日期为ISO8601格式
json_options = json_util.JSONOptions(datetime_representation=DatetimeRepresentation.ISO8601)
# 直接用json_util序列化字典
serialized = json_util.dumps(a.model_dump(), json_options=json_options)
print(serialized)
# 输出示例:{"w": {"$oid": "650000000000000000000000"}, "x": {"$date": "2023-01-01T00:00:00Z"}}

要是想把这个字符串转回可插入MongoDB的对象,用json_util.loads()处理后再插入即可。


补充说明

Pydantic的BaseModel.json()方法的encoder参数,设计目的是传入自定义的JSONEncoder子类(比如继承自json.JSONEncoder的类),而不是直接传序列化函数。你之前的用法不符合参数要求,所以json_options根本传不到json_util.dumps里,才会出现报错。

内容的提问来源于stack exchange,提问作者tubular

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 09:53:22