Pydantic 嵌套模型字段同名,Schema 说明被内层覆盖
use_attribute_docstrings 提取嵌套类源代码时,同名属性说明可能覆盖外层字段。重要接口说明用显式 Field,并核对属性与引用定义。
外层模型字段 x 的说明,生成 JSON Schema 后却变成了内层模型的说明。两个字段恰好同名,而且模型打开了 use_attribute_docstrings=True 时,应检查自动提取属性文档字符串的范围。
Pydantic 2.14.1、core 2.50.1 有明确的嵌套类触发场景。该版从类的源代码建立 AST,再收集字段名后面的字符串;访问嵌套类时没有隔离另一份字段名表,同名说明便可能覆盖。它改变的是字段 description,不等于整数验证器变成了字符串验证器。
对外接口的重要说明直接写进 Field
不依赖自动提取时,可以给需要稳定输出的字段显式指定 description:
from pydantic import BaseModel, ConfigDict, Field
class Outer(BaseModel):
model_config = ConfigDict(use_attribute_docstrings=True)
x: int = Field(description="外层记录编号")
class Inner(BaseModel):
model_config = ConfigDict(use_attribute_docstrings=True)
x: str = Field(description="内层记录名称")
inner: Inner
显式 Field(description=...) 的优先级高于属性文档字符串。不要只给模型类补一段总说明,那不等于修正具体属性的 description。
如果项目本来允许把模型定义移到模块顶层,也可以分别定义 Inner 与 Outer,避免嵌套源代码被一起遍历。但移动类型可能影响导入路径、前向引用和其他工具的类型身份,应作为一次明确的结构调整,不能只为了修一行文档悄悄重排整套模型。
同时看属性节点与引用定义
生成 Schema 后,检查外层 properties.x.description 与内层模型定义中的 x;引用名称以当前输出的 $defs 为准。只看 API 文档首页的标题,可能漏掉具体字段仍然串用了说明。
use_attribute_docstrings 还要求运行时能取得类源代码。交互式定义、打包或动态生成类型是另一组条件;拿不到说明与拿到错误说明,不能直接归成同一原因。
保留修改前的模型与 Schema,修订后比较说明文字、必填字段、类型与校验结果。若仅调整 description 却意外改变了字段约束,应恢复相应模型声明后重新处理。Pydantic 2.14.1 的相关提取逻辑仍有上述范围问题;后续升级应继续以实际 Schema 检查同名嵌套字段。


