2022 年 1 月 21 日,星期五 ·9分鐘閱讀

5 分鐘上手 JSON Schema

如果您到現在才聽過 JSON Schema,那麼您來對地方了。如果您對使用 JSON Schema 很有信心,這篇文章仍然對您有價值,而且您可能仍然會學到一些新東西。

讀完這篇文章,您將會:

  • 了解 JSON Schema 是什麼
  • 知道 JSON Schema 可以做什麼
  • 了解一些關於 JSON Schema 的關鍵術語
  • 了解 JSON Schema 的一些基本運作方式
  • 超越那些擁有多年 JSON Schema 經驗的人(希望如此)

雖然這是一個技術性的介紹,但我們今天不會涵蓋任何程式碼編寫。但我們會提供您幾乎所有程式語言的實作列表連結。

JSON 是什麼?

主要來說,JSON Schema 用於驗證資料。JSON Schema 可以驗證的資料類型是編碼為 JSON 的資料。

JSON 代表 JavaScript 物件表示法,是 JavaScript 的一個子集。JSON 既可供人類閱讀,也可供機器閱讀,使其成為資料交換的熱門格式選擇。

JSON Schema 既是給專案的名稱,也是定義所需驗證的成品 (JSON Schema)。驗證規則透過針對 JSON 資料定義約束條件來表達。

您正在驗證的 JSON 資料稱為「JSON 實例」。

JSON Schema

JSON Schema 專案位於 GitHub,組織名稱為「json-schema-org」。它由多個 git 儲存庫組成,用於追蹤變更並實現規格和支援資源的協作。

JSON Schema 規格由技術規格文件組成,目前透過網際網路工程任務組 (IETF) 以一系列「個人草案」的形式正式發布。「個人草案」是指 IETF 工作組發布在 IETF 上的文件類別。

JSON Schema 文件本身是用 JSON 編寫的。以 JSON 編寫意味著幾乎所有程式語言都可以讀取它,使其成為一個可互通的驗證解決方案。它也可以使用其他轉換為 JSON 的格式編寫,或者使用可以序列化為 JSON 的程式碼編寫。

JSON Schema(文件)

我們提到 JSON Schema 本身是 JSON。過去,JSON 的根層級必須是物件或陣列,但現在,它也可以是任何允許的值。

JSON Schema 可以是物件或布林值。布林值形式的結果與驗證斷言結果相同。物件形式允許使用關鍵字和值來表達驗證的約束條件。

JSON Schema 是基於約束條件的,這表示任何未定義(或約束)的內容都是允許的,並被視為有效。

允許將布林值作為 Schema 看起來可能很奇怪,但我們稍後將探討為什麼它很有用。現在,讓我們看看我們的第一個範例 Schema。

約束條件簡介

資料
{}
一個空物件
資料
true
「true」布林值
資料
false
「false」布林值
資料
{ "not": { } }
Not,空物件

讓我們輪流取得每個 Schema 並說明驗證結果。

空物件 Schema 沒有表達任何約束條件。任何實例資料都會被視為有效。「true」布林值 Schema 將始終斷言實例資料有效。

您可能已經猜到了,剩餘的兩個 Schema 的情況正好相反。「false」布林值 Schema 將始終斷言為 false,而「Not,空物件」Schema 將具有相同的結果。

not 關鍵字採用 JSON Schema 作為其值。這些「schema 值」稱為子 schema。子 schema 會套用到實例資料,並且反轉產生的斷言。正如我們現在所知,空物件 schema 會產生「true」斷言,因此反轉是「false」。

物件 Schema

物件 Schema 中的索引鍵是 JSON Schema 關鍵字。這些關鍵字有四個類別:識別符號、應用程式、斷言和註釋。某些關鍵字不適合這些類別,因為它們具有獨特的功能。

$schema 關鍵字具有獨特的功能。此關鍵字的值是 URI,用於識別處理 schema 時要使用的 JSON Schema 方言。

您可以將 JSON Schema 方言視為一組具有定義含義的關鍵字。在大多數情況下,您將處理的不同方言只是 JSON Schema 的不同版本(或「草案」)。

最佳實務是使用 $schema 關鍵字定義正在使用的 JSON Schema 方言。這樣做時,如果實作找到它們不支援的 JSON Schema 版本,則應擲回錯誤。

如果您的 Schema 未定義它正在使用的 JSON Schema 方言,則實作可以選擇任何方言。當與不支援該版本的實作一起使用時,可能會導致錯誤的肯定結果。

在本簡介中,我們將使用 JSON Schema 的 2020-12 版本,但是,您將學習的大部分內容都適用於當今生產中使用的幾乎所有版本。

2020-12 JSON Schema 方言 URI 是 https://json-schema.dev.org.tw/draft/2020-12/schema

斷言

請記住,JSON Schema 提供基於約束條件的驗證,JSON Schema 定義當套用到實例時,提供斷言結果(通過或失敗)的關鍵字。

「const」關鍵字

最簡單的斷言關鍵字是 const。該值可以是任何有效的 JSON。若要通過驗證,資料必須與 const 的值相同。以下是一個範例

schema
{ "const": 1234 }
資料
1234
符合 schema
有效 - 完全相同
資料
"foobar"
不符合 schema
無效 - 不相同

「type」關鍵字

另一個斷言關鍵字是 type。它的值是一個字串陣列,這些字串是允許的類型。這些類型是 JSON 定義的六個基本類型,加上「integer」。讓我們來看一個範例。

schema
{ "type": ["object", "boolean", "null"] }
資料
{ "ok": "yes" }
符合 schema
有效 - 允許使用物件。
資料
true
符合 schema
有效 - 允許使用布林值。
資料
null
符合 schema
有效 - 允許使用 Null。
資料
123
不符合 schema
無效 - 不允許使用數字。
資料
"foobar"
不符合 schema
無效 - 不允許使用字串。

這兩個斷言關鍵字適用於 JSON 中的任何資料類型,但某些斷言關鍵字僅適用於特定類型。如果關鍵字不適用於實例資料,則會被忽略,並且不執行任何驗證。

「required」關鍵字

required 是一個斷言關鍵字,僅適用於物件。讓我們透過一些範例來探討其含義。

{ "required": ["name"] } - 我們的 JSON Schema { "name": "Bob" } - 有效 - 「name」在物件中。{ "fullName": "Bob" } - 無效 - 物件中缺少「name」。"Bob" - 有效 - required 關鍵字僅適用於物件。true - 有效 - 與上述相同。

這可能令人驚訝,但它允許組成僅在給定特定資料類型時才在邏輯上才有意義的約束。

您應該在同一個 Schema 中將 type 與其他關鍵字結合使用,以避免類型預期不符的情況。

應用器

驗證首先將根 Schema 應用於完整的實例文件。應用器關鍵字將子 Schema 應用於實例位置。

「properties」關鍵字

最常用的應用器關鍵字是 properties,它具有物件值,其中的值是子 Schema。讓我們看看它的實際作用。

schema
{ "properties": { "name": { "type": ["string"] } }}
我們的 JSON Schema
資料
{ "name": "Alice"}
符合 schema
實例具有 name,它是一個字串
資料
{ "fullName": "Alice"}
符合 schema
實例物件沒有 `name` 屬性
資料
[ "name", 123 ]
符合 schema
實例不是一個物件,因此 `properties` 不適用。

子模式只會應用到實例位置中,其鍵值與實例位置物件中的鍵值相符之處。

如果您想確保實例資料是一個物件,請使用 type 關鍵字。

如果您想確保物件具有 "name" 屬性,請使用 required 關鍵字。

重點回顧

JSON Schema 看似無法運作的最常見原因是缺少完全必要的約束。

JSON Schema 是「基於約束」的,而關鍵字可能只適用於正確的資料類型。使用多個關鍵字來加強約束,可讓您確保類型特定的關鍵字不匹配由不同的關鍵字處理。

識別子模式,並了解 Schema 始終可以是布林值,可讓您確認關於正確適用性的假設。如果需要,子模式始終可以單獨進行測試。

後續步驟 / 延伸閱讀

希望您發現這份關於 JSON Schema 基本原理的簡短介紹,有助於您理解、推論和開發 JSON Schema。

我目前建議撰寫 JSON Schema 時使用 VSCode。當檔案處於 JSON 語言模式,且在根物件中新增了 $schema 值時,VSCode 會提供自動完成和 IntelliSense 功能(雖然這僅限於 draft-07)。

以下是一些您可能會發現對未來有幫助的地方

Saad Salim 拍攝於 Unsplash