背景
在开发过程中,由于上游数据结构可能存在不一致的情况,例如字段名称不同但含义相同(如有时上游数据中的字段名为 id
,有时为 code
),为了避免手动编写大量重复代码,我们可以利用 Pydantic 提供的功能,轻松处理这些差异。
Pydantic 允许通过别名(alias)进行字段映射,从而解决不同字段名但含义相同的情况,有效减少代码复杂度。
解决方案
旧版本处理方案(Pydantic v1.x)
在 Pydantic v1.x 中,使用 alias
配合 allow_population_by_field_name
选项来实现字段兼容:
from pydantic import BaseModel, Field
class Foo(BaseModel):
id: int = Field(..., alias="item_id")
field1: str
class Config:
# 允许通过别名或字段名进行数据填充
allow_population_by_field_name = True
# 测试兼容性
foo1 = Foo.parse_obj({"item_id": 123, "field1": "value1"})
foo2 = Foo.parse_obj({"id": 234, "field1": "value1"})
print(foo1) # Foo(id=123, field1='value1')
print(foo2) # Foo(id=234, field1='value1')
新版本处理方案(Pydantic v2.x)
Pydantic v2.x 对配置做了一些调整,将 allow_population_by_field_name
替换为 populate_by_name
。新的配置更加简洁,也引入了新的验证方法。
官方文档参考:Pydantic 配置文档
方案一:通过 Config
配置类
from pydantic import BaseModel, Field
class Foo(BaseModel):
id: int = Field(..., alias="item_id")
field1: str
class Config:
# 使用字段名称进行填充
populate_by_name = True
# 测试兼容性
foo1 = Foo.model_validate({"item_id": 123, "field1": "value1"})
foo2 = Foo.model_validate({"id": 234, "field1": "value1"})
print(foo1) # Foo(id=123, field1='value1')
print(foo2) # Foo(id=234, field1='value1')
方案二:通过 ConfigDict
Pydantic v2.x 提供了 ConfigDict
来配置模型行为,使用方式如下:
from pydantic import BaseModel, Field, ConfigDict
class Foo(BaseModel):
model_config = ConfigDict(populate_by_name=True)
id: int = Field(..., alias="item_id")
field1: str
# 测试兼容性
foo1 = Foo.model_validate({"item_id": 123, "field1": "value1"})
foo2 = Foo.model_validate({"id": 234, "field1": "value1"})
print(foo1) # Foo(id=123, field1='value1')
print(foo2) # Foo(id=234, field1='value1')
结果说明
无论上游传递的字段名是 item_id
还是 id
,通过设置 alias
和启用 populate_by_name
配置,都可以兼容不同的字段名称,同时确保数据的一致性。这种方法特别适合处理复杂的、变化频繁的上游接口数据。