序列化與輸出
序列化(serialization)是把 Pydantic 模型轉回 dict 或 JSON 字串的過程,主要用 model_dump() 與 model_dump_json() 兩個方法。本頁說明兩者的差別、如何挑選或排除欄位、如何略過預設值與 None,以及用 @field_serializer 自訂某個欄位的輸出格式。
model_dump 和 model_dump_json 差在哪?
from datetime import datetime
from decimal import Decimal
from pydantic import BaseModel
class Invoice(BaseModel):
number: str
amount: Decimal
issued_at: datetime
inv = Invoice(number="A001", amount="1290.50", issued_at="2026-10-11T10:00:00")
print(inv.model_dump())
# {'number': 'A001', 'amount': Decimal('1290.50'), 'issued_at': datetime.datetime(2026, 10, 11, 10, 0)}
print(inv.model_dump(mode="json"))
# {'number': 'A001', 'amount': '1290.50', 'issued_at': '2026-10-11T10:00:00'}
print(inv.model_dump_json())
# {"number":"A001","amount":"1290.50","issued_at":"2026-10-11T10:00:00"}
| 方法 | 回傳 | 特殊型別 | 適用 |
|---|---|---|---|
model_dump() |
dict |
保留 Python 物件(datetime、Decimal) |
在 Python 程式內繼續處理 |
model_dump(mode="json") |
dict |
轉成 JSON 相容的值 | 交給其他需要 dict 的 JSON 工具 |
model_dump_json() |
str |
轉成 JSON 相容的值 | 寫檔、送 HTTP、存快取;由 Rust 直接輸出,最快 |
不要寫 json.dumps(model.model_dump())
datetime、Decimal 會讓 json.dumps 報錯,而且多轉了一次。直接用 model_dump_json(),需要排版時加上 indent=2。
如何只輸出部分欄位?
from pydantic import BaseModel, Field
class User(BaseModel):
id: int
name: str
email: str
password_hash: str = Field(exclude=True) # 永遠不輸出
nickname: str | None = None
role: str = "member"
u = User(id=1, name="Alice", email="a@example.com", password_hash="xxx")
print(u.model_dump(include={"id", "name"})) # {'id': 1, 'name': 'Alice'}
print(u.model_dump(exclude={"email"}))
# {'id': 1, 'name': 'Alice', 'nickname': None, 'role': 'member'}
print(u.model_dump(exclude_none=True)) # 略過值為 None 的欄位
print(u.model_dump(exclude_unset=True)) # 只保留建立時明確傳入的欄位
print(u.model_dump(exclude_defaults=True)) # 略過等於預設值的欄位
| 參數 | 用途 |
|---|---|
include / exclude |
指定要保留或排除的欄位,巢狀模型可用 dict 指定 |
exclude_none |
略過 None,常用於輸出精簡 JSON |
exclude_unset |
只輸出使用者真的有傳的欄位,適合實作 PATCH 部分更新 |
exclude_defaults |
略過等於預設值的欄位 |
by_alias |
使用 alias 當輸出的鍵名 |
敏感欄位(密碼雜湊、內部 ID)建議直接在 Field(exclude=True) 宣告,比每次呼叫時記得排除更可靠。
如何自訂某個欄位的輸出格式?
用 @field_serializer,只影響輸出,不影響驗證與屬性值:
from datetime import datetime
from pydantic import BaseModel, field_serializer
class Event(BaseModel):
title: str
starts_at: datetime
price: float
@field_serializer("starts_at")
def format_date(self, v: datetime) -> str:
return v.strftime("%Y/%m/%d %H:%M")
@field_serializer("price")
def round_price(self, v: float) -> float:
return round(v, 1)
e = Event(title="Pydantic 讀書會", starts_at="2026-10-20T19:00:00", price=99.95)
print(e.model_dump_json())
# {"title":"Pydantic 讀書會","starts_at":"2026/10/20 19:00","price":100.0}
需要改變整個模型的輸出結構時,使用 @model_serializer。
輸出的 JSON 中文變成 \uXXXX 怎麼辦?
不會。model_dump_json() 預設直接輸出 UTF-8 中文字元,不會跳脫成 \u 編碼;這點和標準函式庫 json.dumps 預設 ensure_ascii=True 不同。