跳轉至

建立 2026-10-11 更新 2026-10-11

序列化與輸出

序列化(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 不同。

相關資料