本文详解如何使用 skipjsonschema 精准排除 pydantic 模型字段在 model_json_schema() 中的输出,避免 field(exclude=true) 等误用方式导致 schema 仍残留字段的问题。
本文详解如何使用 skip
js
onschema 精准排除 pydantic 模型字段在 model_
json
_schema() 中的输出,避免 field(exclude=true) 等误用方式导致 schema 仍残留字段的问题。
在 Pydantic(尤其是 v2.x)中,开发者常混淆「序列化排除」与「Schema 排除」两个概念:
Field(exclude=True) 或 model_dump(exclude=...) 仅影响运行时数据序列化(如 model_dump() / model_json()),
不影响 JSON Schema 生成
;
Field(exclude_schema=True) 是
无效参数
——Pydantic v2 并未实现该参数,它会被静默忽略,因此字段仍会出现在 model_json_schema() 输出中(正如问题示例所示)。
✅ 正确方案:使用 pydantic.json_schema.SkipJsonSchema 类型包装器。
SkipJsonSchema[T] 是 Pydantic 官方提供的类型注解工具,用于
声明性地告知 JSON Schema 生成器:此字段不应出现在任何 Schema 定义中
,包括属性定义、required 列表及 $defs 引用。
✅ 正确用法示例
输出 Schema 将
不包含 items_dict 字段
:
⚠️ 注意事项与最佳实践
仅作用于 Schema,不影响模型行为
:SkipJsonSchema 不改变字段的验证、默认值、赋值逻辑或序列化行为。若还需运行时排除该字段,请额外配合 exclude 参数:
Find JSON Path Online
Easily find JSON paths within JSON objects using our intuitive Json Path Finder
下载
不可与 Field(...) 混合用于同一字段
:SkipJsonSchema 是类型注解层级的声明,应直接用于字段类型,而非 Field() 的参数。以下写法错误:
支持嵌套与泛型
:可安全用于复杂类型,如 SkipJsonSchema[List[MyModel]]、SkipJsonSchema[Optional[Dict[str, Any]]] 等。
文档兼容性
:生成的 OpenAPI/Swagger 文档(如 FastAPI)会自动尊重 SkipJsonSchema,确保 API 文档不暴露内部字段。
✅ 总结
目标推荐方式排除 JSON Schemafield_name: SkipJsonSchema[T]排除序列化输出field_name: T = Field(..., exclude=True)同时排除两者field_name: SkipJsonSchema[T] = Field(..., exclude=True)
牢记:
Schema 排除 ≠ 序列化排除
。SkipJsonSchema 是 Pydantic v2 中专为 Schema 场景设计的精准控制机制,是解决“字段仍在 schema 中出现”问题的唯一可靠方案。
from pydantic.json_schema import SkipJsonSchema
from pydantic import BaseModel
import json
class MyItem(BaseModel):
name: str
data: str
class MyObject(BaseModel):
# ✅ 此字段将完全从 JSON Schema 中消失
items_dict: dict[str, MyItem] = SkipJsonSchema[dict[str, MyItem]]
# 其他正常字段照常参与 schema 生成
title: str
version: int = 1
# 验证效果
schema = MyObject.model_json_schema()
print(json.dumps(schema, indent=2)){
"properties": {
"title": {
"title": "Title",
"type": "string"
},
"version": {
"default": 1,
"title": "Version",
"type": "integer"
}
},
"required": ["title"],
"title": "MyObject",
"type": "object"
}# 同时排除 schema 和序列化结果
internal_cache: SkipJsonSchema[dict] = Field(default_factory=dict, exclude=True)# ❌ 错误:SkipJsonSchema 是类型,不是 Field 参数
bad_field: str = Field(..., default=SkipJsonSchema[str])