Python使用Pydantic模型时如何便捷访问键未知的嵌套字典
解决方案
方案1:给Pydantic基类扩展通用get方法(推荐)
无需修改现有业务模型的字段结构,全项目复用性最高,完全兼容原生字典的链式get访问习惯:
from typing import Any, Dict, Optional from pydantic import BaseModel class BaseModelWithGet(BaseModel): def get(self, key: str, default: Any = None) -> Any: value = getattr(self, key, default) if isinstance(value, dict): return _DictWithGet(value) if isinstance(value, BaseModelWithGet): return value return value class _DictWithGet(dict): def get(self, key: str, default: Any = None) -> Any: value = super().get(key, default) if isinstance(value, BaseModelWithGet): return value if isinstance(value, dict): return _DictWithGet(value) return value
原有业务模型只需要调整继承的父类即可:
class EventModel(BaseModelWithGet): eventId: str eventName: str class UserModel(BaseModelWithGet): userId: str events: Dict[str, EventModel]
使用效果和原生字典完全一致:
unknown_id = '987' # 不存在的ID直接返回默认值,无需额外判断 event_name = user.get("events", {}).get(unknown_id, {}).get("eventName", "未知事件") print(event_name) # 输出:未知事件 # 存在的ID正常取值 event_name = user.get("events", {}).get("xyz", {}).get("eventName", "未知事件") print(event_name) # 输出:User log in
方案2:临时转字典访问
如果不想调整现有模型定义,仅需单次访问嵌套值,可直接将Pydantic模型转成原生字典后使用链式get:
# Pydantic V2 写法 event_name = user.model_dump()["events"].get(unknown_id, {}).get("eventName") # Pydantic V1 写法 event_name = user.dict()["events"].get(unknown_id, {}).get("eventName")
方案3:定制ID映射字典返回空模型
如果固定某类ID映射的模型结构确定,可以自定义字典类,访问不存在的键时自动返回空模型,进一步简化访问写法:
from typing import TypeVar, Dict from pydantic import BaseModel, field_validator T = TypeVar('T', bound=BaseModel) class IDMap(Dict[str, T]): def __init__(self, model_type: type[T], *args, **kwargs): super().__init__(*args, **kwargs) self.model_type = model_type def __getitem__(self, key: str) -> T: return self.get(key, self.model_type()) # 业务模型调整字段类型 class UserModel(BaseModel): userId: str events: IDMap[EventModel] @field_validator('events', mode='before') def validate_events(cls, v): return IDMap(EventModel, v)
使用时直接访问不会抛出KeyError:
# 不存在的ID返回空EventModel,若EventModel字段设置了默认值会直接读取默认值 print(user.events[unknown_id].eventName)
方案选型参考
- 方案1适配性最高,支持任意层级的嵌套模型,无需针对单个字段做特殊处理
- 方案2改动量最小,适合临时单次使用场景
- 方案3访问写法最简洁,仅适合固定结构的ID映射场景
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

