JSON Schema
JSON Schema 是描述 JSON 資料結構的標準格式,Pydantic 可以用 model_json_schema() 從模型自動產生。這份 Schema 是 FastAPI 自動產生 API 文件(OpenAPI)、LLM 結構化輸出與工具呼叫(tool calling)的基礎:模型定義一次,文件、前端表單、AI 都讀同一份規格。本頁說明如何產生 Schema,以及加入說明與範例讓它更好用。
如何從模型產生 JSON Schema?
import json
from pydantic import BaseModel, Field
class Book(BaseModel):
"""一本書的基本資料。"""
title: str = Field(description="書名")
pages: int = Field(gt=0, description="頁數")
tags: list[str] = []
print(json.dumps(Book.model_json_schema(), ensure_ascii=False, indent=2))
輸出:
{
"description": "一本書的基本資料。",
"properties": {
"title": {
"description": "書名",
"title": "Title",
"type": "string"
},
"pages": {
"description": "頁數",
"exclusiveMinimum": 0,
"title": "Pages",
"type": "integer"
},
"tags": {
"default": [],
"items": {
"type": "string"
},
"title": "Tags",
"type": "array"
}
},
"required": [
"title",
"pages"
],
"title": "Book",
"type": "object"
}
可以看到:類別的 docstring 變成 description,Field 的限制(gt=0)變成 exclusiveMinimum,沒有預設值的欄位列在 required。
為什麼 description 很重要?
description 不只給人看。FastAPI 會把它顯示在 Swagger UI 文件上;把模型交給 LLM 當作輸出格式或工具參數時,模型主要依靠 description 理解每個欄位該填什麼。欄位名稱看不出意義時,一定要補上說明:
from pydantic import BaseModel, Field
class WeatherQuery(BaseModel):
city: str = Field(description="城市名稱,使用繁體中文,例如「台北市」")
days: int = Field(default=1, ge=1, le=7, description="要查詢未來幾天的天氣預報")
如何在 Schema 裡加上範例?
examples 會寫進 Schema,FastAPI 文件會用它預先填好「Try it out」的請求內容:
from pydantic import BaseModel, ConfigDict, Field
class CreateUser(BaseModel):
model_config = ConfigDict(
json_schema_extra={"examples": [{"email": "alice@example.com", "age": 30}]}
)
email: str = Field(examples=["alice@example.com"])
age: int = Field(ge=0, examples=[30])
驗證用與輸出用的 Schema 會不一樣嗎?
可能會。例如 @computed_field 只在輸出時存在,有預設值的欄位在輸出時一定有值。model_json_schema(mode="validation")(預設)描述「可以接受的輸入」,mode="serialization" 描述「實際輸出的格式」。FastAPI 會依請求或回應自動選用正確的模式。