
本文详解如何使用 skipjsonschema 正确地将 pydantic 模型字段从生成的 json schema 中完全移除,避免 field(exclude=true, exclude_schema=true) 等无效方式导致的 schema 泄露问题。
本文详解如何使用 skipjsonschema 正确地将 pydantic 模型字段从生成的 json schema 中完全移除,避免 field(exclude=true, exclude_schema=true) 等无效方式导致的 schema 泄露问题。
在 Pydantic(尤其是 v2.x)中,开发者常误以为设置 Field(..., exclude=True, exclude_schema=True) 即可同时屏蔽字段在序列化(如 .model_dump())和 JSON Schema(如 .model_json_schema())中的出现。但正如示例所示,该配置仅影响序列化行为,对 Schema 生成完全无效——items_dict 仍会以完整结构出现在 $defs 和 properties 中,违背了“内部字段不暴露”的设计初衷。
正确且官方推荐的方式是使用 SkipJsonSchema 类型封装器。它不是字段参数,而是一种类型注解修饰符,作用于字段类型本身,向 JSON Schema 生成器明确声明:“此字段不应出现在任何 Schema 输出中”。
✅ 正确用法:SkipJsonSchema[T]
from pydantic.json_schema import SkipJsonSchema
from pydantic import BaseModel
import json
class MyItem(BaseModel):
name: str
data: str
class MyObject(BaseModel):
visible_in_schema: str
# ✅ 完全从 schema 中剔除:既不出现在 properties,也不进入 $defs 引用链
internal_cache: SkipJsonSchema[dict[str, MyItem]]
@property
def items_list(self) -> list[MyItem]:
return list(self.internal_cache.values()) if hasattr(self, 'internal_cache') else []
# 实例化与验证不受影响
obj = MyObject(
visible_in_schema="public",
internal_cache={"i1": MyItem(name="item1", data="data1")}
)
# 查看生成的 Schema —— internal_cache 字段彻底消失
print(json.dumps(obj.model_json_schema(), indent=2))输出 Schema 将仅包含 visible_in_schema 字段,MyItem 类型也不会被自动引入 $defs(除非其他显式引用它的字段存在):
{
"properties": {
"visible_in_schema": {
"title": "Visible In Schema",
"type": "string"
}
},
"required": ["visible_in_schema"],
"title": "MyObject",
"type": "object"
}⚠️ 注意事项与最佳实践
-
SkipJsonSchema 仅作用于 JSON Schema 生成(.model_json_schema()),不影响模型验证、实例化或 .model_dump() 行为。若还需序列化时排除该字段,请额外配合 exclude 参数:
internal_cache: SkipJsonSchema[dict[str, MyItem]] = Field(default_factory=dict, exclude=True)
不要混用 SkipJsonSchema 与 Field(exclude_schema=True) —— 后者已被弃用且无实际效果,Pydantic 会忽略它。
SkipJsonSchema 支持嵌套和泛型,例如 SkipJsonSchema[list[Optional[MyItem]]] 或 SkipJsonSchema[Annotated[str, BeforeValidator(str.upper)]] 均合法。
若字段需参与校验但绝对不可见于外部 Schema(如 API 文档、OpenAPI 规范),SkipJsonSchema 是唯一可靠方案;切勿依赖文档注释或约定隐藏,Schema 生成器必须“感知不到”该字段的存在。
✅ 总结
| 目标 | 推荐方式 | 是否影响 Schema | 是否影响序列化 |
|---|---|---|---|
| 仅隐藏 Schema | SkipJsonSchema[T] | ✅ 彻底排除 | ❌ 保留 |
| 仅隐藏序列化 | Field(..., exclude=True) | ❌ 仍在 Schema 中 | ✅ 排除 |
| 两者都隐藏 | SkipJsonSchema[T] + Field(..., exclude=True) | ✅ 排除 | ✅ 排除 |
始终优先使用 SkipJsonSchema 处理 Schema 隐藏需求——它是 Pydantic 官方为该场景专门设计的语义化、类型安全且向后兼容的解决方案。










