TypeAdapter 與 dataclass
不是所有資料都需要包成 BaseModel。TypeAdapter 讓你直接驗證任何型別,例如 list[int]、dict[str, float] 或 TypedDict;pydantic.dataclasses.dataclass 則讓你保留標準 dataclass 的寫法,同時得到 Pydantic 的驗證。本頁說明這兩個工具的用法,以及何時該選哪一種。
如何驗證一個 list 或 dict,而不必建立模型?
from pydantic import TypeAdapter, ValidationError
scores = TypeAdapter(list[int])
print(scores.validate_python(["1", 2, 3.0])) # [1, 2, 3]
print(scores.validate_json("[4, 5, 6]")) # [4, 5, 6]
try:
scores.validate_python([1, "two"])
except ValidationError as e:
print(e.errors()[0]["loc"]) # (1,)
TypeAdapter 的方法名稱對應 BaseModel:
| BaseModel | TypeAdapter |
|---|---|
Model.model_validate(obj) |
ta.validate_python(obj) |
Model.model_validate_json(s) |
ta.validate_json(s) |
m.model_dump() |
ta.dump_python(obj) |
m.model_dump_json() |
ta.dump_json(obj)(回傳 bytes) |
Model.model_json_schema() |
ta.json_schema() |
外部 API 回傳一個模型陣列怎麼驗證?
API 常回傳最外層是陣列的 JSON,這正是 TypeAdapter 最常見的用途:
from pydantic import BaseModel, TypeAdapter
class User(BaseModel):
id: int
name: str
UserList = TypeAdapter(list[User])
raw = '[{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]'
users = UserList.validate_json(raw)
print(users[1].name) # Bob
重複使用 TypeAdapter
建立 TypeAdapter 時會編譯驗證邏輯,有一定成本。請在模組層級建立一次後重複使用,不要放在迴圈或每次請求的函式裡。
Pydantic dataclass 和 BaseModel 差在哪?
pydantic.dataclasses.dataclass 的寫法和標準 dataclass 完全一樣,只是多了驗證:
from pydantic import Field
from pydantic.dataclasses import dataclass
@dataclass
class Point:
x: float
y: float = Field(default=0, ge=0)
print(Point(x="1.5")) # Point(x=1.5, y=0)
| 比較 | BaseModel |
Pydantic dataclass |
|---|---|---|
| 驗證 | 有 | 有 |
model_dump() 等方法 |
有 | 沒有,需用 TypeAdapter 或 dataclasses.asdict |
| 是否為真正的 dataclass | 否 | 是,可用 dataclasses 模組的工具 |
| 適合 | 大多數情況,功能最完整 | 既有程式已大量使用 dataclass,想加上驗證 |
一般建議:新程式優先用 BaseModel;已經大量使用 dataclass 的程式碼,再考慮 Pydantic dataclass。