JSON 工具箱

draft-07 和 2020-12 該用哪個

結論:2020-12 是當前推薦版本,`$defs`、`prefixItems`、`unevaluatedProperties` 都在這裡;但很多舊驗證器、程式碼產生器仍只認 draft-07。選版本的依據不是新舊,而是「鏈路上每個工具都支援哪個」。

深入約 4 分鐘發佈於 2026-10-30更新於 2026-10-30
JSON Schema 各版本的差異與選型建議

結論:新專案直接用 2020-12,只要驗證器、程式碼產生器或 OpenAPI 工具鏈中有元件只認 draft-07,就退回 draft-07,並在檔案裡寫死 $schema。

一句話:新專案用 2020-12,鏈路上有老元件就退回 draft-07。

版本演進速覽

版本 年份 關鍵變化
draft-04 2013 早期廣泛使用,id 而非 $id
draft-06 2017 加 const、propertyNames
draft-07 2018 加 if/then/else、readOnly、contentMediaType,相容性最好
2019-09 2019 $defs 取代 definitions,加 unevaluatedProperties
2020-12 2020 prefixItems 取代陣列元組寫法,$dynamicRef,當前推薦

2020-12 好用的地方

陣列元組寫法統一了。 draft-07 裡用 items: [{...}, {...}] 表示「第一個元素是 A、第二個是 B」,additionalItems 控制後續;2020-12 改成 prefixItems + items,語意清楚得多。

$defs 更規範。 2019-09 之後官方統一為 $defs,新工具預設按這個找。

unevaluatedProperties 解決組合難題。 用 allOf 組合多個 Schema 時,additionalProperties: false 會誤殺其他分支定義的欄位;unevaluatedProperties: false 只看「最終求值過的屬性」,這才是組合場景想要的行為。

什麼時候必須退回 draft-07

情況 原因
使用 OpenAPI 3.0 規範內建的就是 draft-04/07 的子集
驗證器是老版本(ajv 6、部分 Java 函式庫) 不認識 prefixItems、$dynamicRef
平台方指定 Schema 版本 例如某些低程式碼平台、API 閘道
產生程式碼的工具只支援到 07 產生器會靜默忽略不認識的關鍵字

判斷方法很直接:拿一段用 prefixItems 的 Schema 丟進你的驗證器,如果它不報「未知關鍵字」而是直接通過驗證,說明它在靜默忽略——這比報錯更危險。

混用時的注意事項

永遠寫 $schema。 不寫時不同函式庫的預設版本不一樣,ajv 預設 draft-07,部分 Python 函式庫預設 2020-12。同一個檔案在兩處驗證結果不同,排查起來非常費勁。

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/schemas/order.json",
  "type": "object"
}

別跨版本引用。 $ref 指向另一個版本的 Schema,行為未定義。

升級要成批做。 一個專案裡同時存在兩種版本,等於把「這份檔案到底按哪個版本解釋」變成人員記憶。

常見問題

如何判斷驗證器是否真的支援 2020-12?

拿一段使用 prefixItems 的 Schema 丟進驗證器:報「未知關鍵字」說明不支援,直接通過驗證則說明它在靜默忽略,這比報錯更危險。

為什麼要讓整個專案統一版本?

一個專案同時存在兩種版本,等於把「這份檔案按哪個版本解釋」變成人員記憶,早晚出錯。升級應當成批完成。

是否可以不寫 $schema?

不建議。不寫時不同函式庫的預設版本不一樣,ajv 預設 draft-07,部分 Python 函式庫預設 2020-12,同一個檔案在兩處驗證結果可能不同。

延伸閱讀