如何为Pydantic拆分式时间戳模型添加Schema描述及自定义日期验证?
问题与解决方案
问题背景
我已创建一个继承自RootModel的Pydantic模型TimestampWithSplit,可将形如{ "date": "2021-07-01", "time": "12:36:23" }的JSON对象解析为datetime(2021, 7, 1, 12, 36, 23),同时能生成基础JSON Schema。现有代码如下:
from datetime import datetime from typing import Any, Type from pydantic import RootModel from pydantic_core import core_schema from pydantic_core.core_schema import GetCoreSchemaHandler class TimestampWithSplit(RootModel): root: datetime @classmethod def __get_pydantic_core_schema__( cls, source: Type[Any], handler: GetCoreSchemaHandler ) -> core_schema.CoreSchema: return core_schema.chain_schema( [ core_schema.typed_dict_schema( { "date": core_schema.typed_dict_field(core_schema.date_schema()), "time": core_schema.typed_dict_field(core_schema.time_schema()), } ), core_schema.no_info_plain_validator_function(cls.validate_to_datetime), ] ) @staticmethod def validate_to_datetime(value: dict) -> datetime: return datetime.combine(value["date"], value["time"])
需要完成两项优化:
- 为生成的JSON Schema的
date和time字段添加描述信息 - 为
date字段添加自定义验证,支持解析单数字的日/月(如2021-7-1)
解决方案
你的实现路径是正确的,通过__get_pydantic_core_schema__自定义核心Schema是实现这类需求的标准方式。以下是整合两项需求后的完整代码:
完整实现代码
from datetime import datetime from typing import Any, Type from pydantic import RootModel from pydantic_core import core_schema from pydantic_core.core_schema import GetCoreSchemaHandler class TimestampWithSplit(RootModel): root: datetime @classmethod def __get_pydantic_core_schema__( cls, source: Type[Any], handler: GetCoreSchemaHandler ) -> core_schema.CoreSchema: # 1. 构建带自定义验证和Schema描述的date字段Schema def validate_custom_date(value: str) -> datetime.date: # 支持两种日期格式:带前导零和不带前导零 for fmt in ("%Y-%m-%d", "%Y-%-m-%-d"): try: return datetime.strptime(value, fmt).date() except ValueError: continue raise ValueError(f"无效日期格式: {value},请使用YYYY-MM-DD或YYYY-M-D格式") custom_date_schema = core_schema.no_info_plain_validator_function(validate_custom_date) custom_date_schema = core_schema.with_json_schema( custom_date_schema, { "format": "date", "title": "Date", "type": "string", "description": "ISO格式日期,支持YYYY-MM-DD或YYYY-M-D格式" } ) # 2. 构建带Schema描述的time字段Schema custom_time_schema = core_schema.with_json_schema( core_schema.time_schema(), { "format": "time", "title": "Time", "type": "string", "description": "ISO格式时间,例如HH:MM:SS" } ) # 组装最终的核心Schema return core_schema.chain_schema( [ core_schema.typed_dict_schema( { "date": core_schema.typed_dict_field(custom_date_schema), "time": core_schema.typed_dict_field(custom_time_schema), } ), core_schema.no_info_plain_validator_function(cls.validate_to_datetime), ] ) @staticmethod def validate_to_datetime(value: dict) -> datetime: return datetime.combine(value["date"], value["time"])
关键实现说明
添加JSON Schema描述
- 使用
core_schema.with_json_schema()方法,为每个字段的核心Schema附加自定义JSON Schema元数据,其中包含description字段,满足你对Schema的定制需求。 - 对于
time字段,直接基于内置的time_schema()添加描述即可;对于date字段,先绑定自定义验证器,再添加Schema描述。
- 使用
自定义日期验证逻辑
- 在
__get_pydantic_core_schema__内部定义validate_custom_date函数,尝试多种日期格式解析(带前导零和不带前导零的格式),确保支持2021-7-1这类输入。 - 将验证器包装为
core_schema.no_info_plain_validator_function,作为date字段的核心验证逻辑。
- 在
效果验证
# 测试解析单数字月日的JSON json_input = '{"date": "2021-7-1", "time": "12:36:23"}' result = TimestampWithSplit.model_validate_json(json_input) print(result.root) # 输出: 2021-07-01 12:36:23 # 查看生成的JSON Schema schema = TimestampWithSplit.model_json_schema() print(schema["properties"]["date"]["description"]) # 输出: ISO格式日期,支持YYYY-MM-DD或YYYY-M-D格式 print(schema["properties"]["time"]["description"]) # 输出: ISO格式时间,例如HH:MM:SS
内容的提问来源于stack exchange,提问作者Matthew Jones
相关产品推荐
相关产品推荐

