JSON 驗證與 Schema 設計最佳實踐
為什麼 JSON 驗證很重要
API 是現代應用程式的骨幹,而 JSON 是它們的通用語言。但如果沒有適當的驗證,格式錯誤或惡意的 JSON 可能會讓你的服務崩潰、損壞資料庫,或開啟安全漏洞。我見過因為單一缺少的欄位或非預期的型別而導致的生產環境中斷。JSON 驗證不只是捕捉錯字——它關乎強制執行契約、改善錯誤訊息,並保護你的系統。
在本文中,我們將涵蓋設計 JSON Schema 和驗證酬載的實用最佳實踐。無論你是在建構 REST API、GraphQL 解析器或微服務,這些原則都能幫助你晚上睡得更好。
1. 從清晰的 Schema 開始
Schema 是 API 的契約。它定義了允許哪些欄位、它們的型別以及任何限制。沒有它,你就是在盲目飛行。使用 JSON Schema(一種標準化詞彙)來描述你的資料。它與語言無關,且被廣泛支援。
以下是使用者物件的最小範例:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"id": { "type": "integer", "minimum": 1 },
"name": { "type": "string", "minLength": 1 },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0, "maximum": 150 }
},
"required": ["id", "name", "email"],
"additionalProperties": false
}
重點:required 確保必填欄位;additionalProperties: false 拒絕未知欄位(對嚴格 API 很有用)。
2. 盡早且頻繁地驗證
在邊緣驗證——在業務邏輯執行之前。這能防止無效資料傳播。在 Node.js 中,你可以使用 Ajv 這類函式庫;在 Python 中,使用 jsonschema;在 Go 中,使用 gojsonschema。務必驗證傳入請求和傳出回應(以捕捉錯誤)。
Python 範例:
from jsonschema import validate, ValidationError
try:
validate(instance=request.json, schema=user_schema)
except ValidationError as e:
return {"error": e.message}, 400
回傳清晰的錯誤訊息——它們能幫助客戶端快速修正問題。
3. 為演進而設計
API 會改變。你的 Schema 應該能容納新增內容,而不會破壞客戶端。遵循這些規則:
- 絕不刪除或重新命名欄位,除非進行版本升級。
- 讓新欄位保持選填,除非它們是關鍵的。
- 在 URL 中使用版本控制(例如
/v1/users)或媒體類型。 - 偏好附加性變更——新增欄位,而非修改現有欄位。
這種做法符合 Postel 定律:對發送的內容保守,對接受的內容寬容。但不要過於寬容——嚴格驗證能及早捕捉錯誤。
4. 小心處理型別
JSON 的型別有限:string、number、boolean、object、array、null。注意以下幾點:
- 數字:JSON 不區分整數與浮點數。若需要整數,請使用
type: integer。 - 日期:使用 ISO 8601 字串(例如
2026-01-15T10:00:00Z),並以format: date-time驗證。 - 列舉:將值限制在已知集合中,以避免無效狀態。
- Null 與缺少:決定是否允許 null。通常,省略欄位比傳送 null 更好。
5. 保護你的驗證
驗證是一種安全控制。攻擊者可能會傳送過大的酬載、深度嵌套的物件或非預期的型別來造成阻斷服務。透過以下方式緩解:
- 大小限制:拒絕超過特定大小(例如 1MB)的酬載。
- 深度限制:防止過度嵌套的 JSON(例如最大深度 10)。
- 嚴格 Schema:不允許額外屬性,以避免注入非預期的欄位。
- 淨化字串:即使在驗證之後,也要轉義輸出以防止 XSS。
此外,請在伺服器端驗證——絕不要只信任客戶端驗證。
6. 使用驗證函式庫比較表
選擇正確的函式庫取決於你的語言和效能需求。以下是快速比較:
| 語言 | 函式庫 | 主要功能 |
|---|---|---|
| JavaScript/Node.js | Ajv | 快速,支援 JSON Schema draft-07 |
| Python | jsonschema | 成熟,易於使用 |
| Go | gojsonschema | 原生效能 |
| Java | everit-org/json-schema | 全面支援 |
所有這些函式庫都實作 JSON Schema,因此你的 Schema 是可攜的。
7. 為你的 Schema 撰寫文件
Schema 只有在開發人員理解它時才有用。使用 OpenAPI(前身為 Swagger)或 JSON Schema 的 description 關鍵字等工具,從你的 Schema 產生 API 文件。為每個欄位包含範例。
若要快速檢查,你可以使用 JSON 格式化工具 手動格式化和驗證 JSON。它有助於在深入 Schema 驗證之前發現語法錯誤和結構問題。
8. 測試你的 Schema
Schema 就是程式碼——測試它們。使用有效和無效的酬載撰寫單元測試,以確保你的驗證規則如預期運作。json-schema-test-suite 這類工具可以提供協助。此外,考慮服務之間的契約測試,以及早捕捉不匹配的情況。
常見問題
什麼是 JSON Schema,為什麼我應該使用它?
JSON Schema 是一種描述 JSON 資料結構的標準。它讓你可以定義型別、必填欄位和限制,從而實現自動驗證和文件化。它被廣泛支援於各種語言。
在 JSON 驗證中,我該如何處理額外屬性?
預設情況下,JSON Schema 允許額外屬性。設定 additionalProperties: false 來拒絕未知欄位,這能提升安全性並捕捉錯字。然而,在 API 演進時要謹慎——嚴格的 Schema 可能會破壞傳送額外欄位的客戶端。
我可以使用 JSON Schema 進行請求和回應驗證嗎?
當然可以。驗證傳入請求和傳出回應,以確保資料完整性。回應驗證能在你自己程式碼中的錯誤到達客戶端之前捕捉它們。
結論
JSON 驗證和 Schema 設計是穩健 API 的基礎。透過定義清晰的 Schema、及早驗證、規劃演進並保護你的端點,你能建構可靠且可維護的系統。從 Schema 開始,選擇驗證函式庫,並徹底測試。未來的你(以及你的使用者)會感謝你。