這篇文章將教你如何在 FastAPI 中定義與接收請求主體 (Request Body),當客戶端需要傳送 JSON 格式的詳細資料給伺服器(例如註冊表單或新增商品)時,就必須使用請求主體 (Request Body)。
什麼是請求主體 (Request Body)?
請求主體 (Request Body) 是客戶端(例如手機 APP、網頁前端)發送給 API 的具體資料內容。它通常以 JSON 格式傳遞,適合包含多個欄位的複雜資料,這與單純透過網址傳遞參數(Query Parameters)不同。
Request Body 基礎概念
Pydantic 模型
FastAPI 使用Pydantic 來定義資料結構並進行驗證。我們需要創建一個繼承自 BaseModel 的類別,用來告訴 FastAPI 我們期望收到什麼樣的資料。from pydantic import BaseModel
# 定義訂單模型
class FoodOrder(BaseModel):
food_name: str
quantity: int
is_spicy: bool = False
note: str | None = None
這段程式碼定義了一個 FoodOrder 模型:
food_name(字串):必填,餐點名稱。quantity(整數):必填,份數。is_spicy(布林值):選填,預設為False(不加辣)。note(字串或 None):選填,備註欄位,預設為空。
在路徑操作函式中宣告
定義好模型後,將它加入到你的 API 函式參數中,FastAPI 就會自動處理剩下的工作。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# 定義訂單模型
class FoodOrder(BaseModel):
food_name: str
quantity: int
is_spicy: bool = False
note: str | None = None
# 將 order 參數宣告為 FoodOrder 型別
@app.post("/orders/")
def create_order(order: FoodOrder):
return order
當客戶端發送 POST 請求到 /orders/ 時,FastAPI 會自動讀取 JSON Body,驗證它是否符合 FoodOrder 的結構,並將其轉換為 Python 物件注入到 order 參數中。
自動文件與驗證
FastAPI 不僅會自動攔截錯誤格式的資料,還會根據定義好的模型在 /docs 路徑自動生成互動式 API 文件 (Swagger UI)。
// 前往 http://127.0.0.1:8000/docs 測試 API
// 如果 quantity 傳了字串 "兩份" (錯誤型別)
// API 會自動回傳 422 Unprocessable Entity
{
"detail": [
{
"type": "int_parsing",
"loc": [
"body",
"quantity"
],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "兩份"
}
]
}
實作範例
接下來,我們實作一個完整的範例,當收到訂單後,我們根據是否加辣來調整訊息,並計算訂單總結。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# 1. 定義資料模型
class FoodOrder(BaseModel):
food_name: str
quantity: int
price_per_unit: int
is_spicy: bool = False
note: str | None = None
# 2. 建立 POST 請求處理函式
@app.post("/orders/")
def create_order(order: FoodOrder):
# 計算總金額
total_price = order.quantity * order.price_per_unit
# 建立回覆訊息
message = f"已收到訂單:{order.quantity} 份 {order.food_name},總金額 ${total_price}"
if order.is_spicy:
message += " (備註:要加辣🔥)"
if order.note:
message += f" | 客戶備註:{order.note}"
# 使用 model_dump() 將 Pydantic 物件轉回字典,以便回傳 JSON
result = order.model_dump()
result.update({
"total_price": total_price,
"message": message,
})
return result
在此範例中,如果你傳送 JSON Body:
{"food_name": "牛肉麵", "quantity": 2, "price_per_unit": 150, "is_spicy": true}
API 將會回傳包含總金額 300 以及確認訊息 "已收到訂單:2 份 牛肉麵,總金額 $300 (要加辣🔥)" 的 JSON 資料。
常見錯誤與解決方法
1. 忘記繼承 BaseModel
使用一般的 Python class 來定義結構,這會導致 FastAPI 無法正確將其識別為 JSON Body,而可能將其視為查詢參數,導致驗證失敗。
# ❌ 錯誤寫法:沒有繼承 BaseModel
class User:
username: str
# ✅ 正確寫法:繼承 BaseModel
from pydantic import BaseModel
class User(BaseModel):
username: str
2. HTTP 方法使用錯誤
雖然技術上 GET 請求可以攜帶 Body,但在 HTTP 語意規範中,GET 用於「獲取資源」,不應該包含請求主體。若要傳送資料給伺服器處理,請務必使用 POST 或 PUT。
# ❌ 不建議:在 GET 請求中使用 Body
@app.get("/orders/")
def get_order(order: FoodOrder): ...
# ✅ 正確:建立資源使用 POST
@app.post("/orders/")
def create_order(order: FoodOrder): ...
結語
透過 Pydantic 模型,我們可以用非常簡潔的 Python 語法來定義複雜的 API 資料介面。這不僅讓程式碼更易讀,也透過自動驗證減少因為資料格式錯誤導致的 Bug。確保你的模型繼承自 BaseModel,並善用 Python 的型別提示 (Type Hints),就能輕鬆掌握 FastAPI 的請求主體 (Request Body)。











