如何从Pydantic Schema中排除内部字段?
Pydantic内部字段无法排除序列化及Schema的解决方法
我在Pydantic类中定义了一个内部字段items_dict,仅用于内部逻辑处理,不需要被序列化,也不想让它出现在生成的Schema里。尝试使用Field的exclude=True和exclude_schema=True参数后,问题依然存在,生成的Schema中该字段仍会显示。
我的代码实现
from pydantic import BaseModel, Field, root_validator import json class MyItem(BaseModel): name: str = Field(...) data: str = Field(...) def validate_items(items): # 自定义验证逻辑,将列表转为字典 return {item.name: item for item in items} class MyObject(BaseModel): items_dict: dict[str, MyItem] = Field(..., exclude=True, exclude_schema=True) @property def items_list(self): return list(self.items_dict.values()) @root_validator(pre=True) @classmethod def encode_decode_items(cls, values): items = values.get('items_dict') if isinstance(items, dict): values['items_dict'] = list(items.values()) elif isinstance(items, list): values['items_dict'] = validate_items(items) return values obj = MyObject(items_dict=[MyItem(name='item1', data='data1'), MyItem(name='item2', data='data2')]) print(json.dumps(obj.model_json_schema(), indent=2))
问题现象
运行代码后,生成的Schema依然包含items_dict字段:
{ "$defs": { "MyItem": { "properties": { "name": { "title": "Name", "type": "string" }, "data": { "title": "Data", "type": "string" } }, "required": [ "name", "data" ], "title": "MyItem", "type": "object" } }, "properties": { "items_dict": { "additionalProperties": { "$ref": "#/$defs/MyItem" }, "exclude_schema": true, "title": "Items Dict", "type": "object" } }, "required": [ "items_dict" ], "title": "MyObject", "type": "object" }
可行的解决办法
方法1:通过model_config配置全局排除
在MyObject类中添加model_config,同时指定exclude和private_attributes,从根源上排除该字段的序列化和Schema生成:
class MyObject(BaseModel): items_dict: dict[str, MyItem] = Field(...) @property def items_list(self): return list(self.items_dict.values()) @root_validator(pre=True) @classmethod def encode_decode_items(cls, values): items = values.get('items_dict') if isinstance(items, dict): values['items_dict'] = list(items.values()) elif isinstance(items, list): values['items_dict'] = validate_items(items) return values model_config = { "exclude": {"items_dict"}, "private_attributes": {"items_dict"} }
方法2:改用PrivateAttr定义纯内部字段
如果字段仅用于内部逻辑,不需要对外暴露,可以使用PrivateAttr定义(注意字段名需加下划线前缀),这样字段不会被纳入Schema和序列化流程:
from pydantic import PrivateAttr class MyObject(BaseModel): _items_dict: dict[str, MyItem] = PrivateAttr(default_factory=dict) @property def items_list(self): return list(self._items_dict.values()) @root_validator(pre=True) @classmethod def encode_decode_items(cls, values): items = values.pop('items_dict') if isinstance(items, dict): items = list(items.values()) values['_items_dict'] = validate_items(items) return values
这种方式需要调整root_validator的逻辑,将输入的items_dict转为内部的_items_dict。
方法3:序列化时手动排除(仅解决序列化问题)
如果只是不想序列化该字段,但可以接受它出现在Schema中,可在序列化时指定exclude参数:
# 序列化时排除items_dict print(obj.model_dump(exclude={"items_dict"}))
但此方法不会影响Schema生成,仅适用于序列化场景。
内容的提问来源于stack exchange,提问作者Aviad Rozenhek
相关产品推荐
相关产品推荐

