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

如何扩展Pydantic现有类型(如FilePath)添加pattern验证与Schema支持

扩展Pydantic现有类型(如FilePath)并添加自定义Pattern验证

要在保留Pydantic原生类型(如FilePath)所有特性的前提下,添加可自定义的正则pattern验证及JSON Schema支持,可通过以下两种方案实现:

方案一:基于Annotated的便捷类型生成器

通过封装Annotated结合自定义验证器和动态Schema扩展,实现灵活的pattern复用,同时完全继承FilePath的存在性验证逻辑。

代码实现

import re
from typing import Annotated
from pydantic import BaseModel, FilePath, Field, AfterValidator
from pydantic.json_schema import JsonSchemaValue

# 生成路径pattern验证器
def validate_path_pattern(pattern: str):
    def validator(value: str) -> str:
        if not re.fullmatch(pattern, value):
            raise ValueError(f"路径不符合规则: {pattern}")
        return value
    return validator

# 动态向JSON Schema添加pattern字段
def add_pattern_to_schema(pattern: str):
    def schema_extra(schema: JsonSchemaValue, _) -> None:
        # 在原有Schema基础上追加pattern,不覆盖原有字段(如format: path)
        schema['pattern'] = pattern
    return schema_extra

# 生成带自定义pattern的FilePath类型别名
def FilePathWithPattern(pattern: str) -> type:
    return Annotated[
        FilePath,
        AfterValidator(validate_path_pattern(pattern)),  # 先验证路径存在,再检查pattern
        Field(json_schema_extra=add_pattern_to_schema(pattern))
    ]

使用示例

class AppConfig(BaseModel):
    yaml_config: FilePathWithPattern(r".*\.yaml$")
    log_file: FilePathWithPattern(r".*\.log$")

# 验证通过的情况
valid_model = AppConfig(yaml_config="/etc/app/config.yaml", log_file="/var/log/app.log")
print(valid_model)

# 验证失败的情况(路径存在但不符合pattern)
try:
    invalid_model = AppConfig(yaml_config="/etc/app/config.txt", log_file="/var/log/app.log")
except Exception as e:
    print(e)

# 查看生成的JSON Schema(包含pattern字段及原生FilePath的format字段)
print(AppConfig.model_json_schema())

方案二:泛型自定义类型

通过实现Pydantic的类型协议,创建可复用的泛型类型,写法更贴近原生类型系统。

代码实现

import re
from typing import Generic, TypeVar, Any
from pydantic import BaseModel, FilePath, GetCoreSchemaHandler, GetJsonSchemaHandler
from pydantic_core import core_schema
from pydantic.json_schema import JsonSchemaValue

# 定义泛型参数,用于传递pattern字符串
PatternType = TypeVar('PatternType', bound=str)

class FilePathPattern(Generic[PatternType]):
    @classmethod
    def __get_pydantic_core_schema__(
        cls, source_type: Any, handler: GetCoreSchemaHandler
    ) -> core_schema.CoreSchema:
        # 获取泛型参数中的pattern规则
        pattern = source_type.__args__[0]
        # 获取原生FilePath的核心验证逻辑
        file_path_schema = handler(FilePath)
        
        # 追加pattern验证逻辑
        return core_schema.no_info_after_validator_function(
            lambda value: re.fullmatch(pattern, value) or ValueError(f"路径不符合规则: {pattern}"),
            file_path_schema
        )

    @classmethod
    def __get_pydantic_json_schema__(
        cls, core_schema_: core_schema.CoreSchema, handler: GetJsonSchemaHandler
    ) -> JsonSchemaValue:
        # 获取原生FilePath的JSON Schema
        json_schema = handler(core_schema_)
        # 从泛型基类中提取pattern并添加到Schema
        pattern = cls.__orig_bases__[0].__args__[0]
        json_schema['pattern'] = pattern
        return json_schema

使用示例

class AppConfig(BaseModel):
    yaml_config: FilePathPattern[r".*\.yaml$"]
    log_file: FilePathPattern[r".*\.log$"]

# 验证逻辑与方案一完全一致
valid_model = AppConfig(yaml_config="/etc/app/config.yaml", log_file="/var/log/app.log")
print(valid_model)

核心问题解决说明

  1. Field的pattern不被FilePath识别:原生FilePath未实现pattern验证逻辑,通过AfterValidator追加自定义验证器,实现路径存在性验证后的pattern检查。
  2. json_schema_extra写死导致复用性差:通过函数生成动态的schema_extra或泛型参数传递pattern,实现同一类型的多场景复用。
  3. WithJsonSchema丢失原有关键字:两种方案均基于原生FilePath的Schema进行修改(而非替换),保留了format: path等原生字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 07:43:20