開始使用

使用 JSON Schema 建立檔案系統模型

在這個逐步指南中,您將學習如何設計一個 JSON Schema,來反映 /etc/fstab 檔案的結構。

本指南分為以下幾個部分

簡介

並非 fstab 檔案的所有約束都可以單獨使用 JSON Schema 來建立模型; 但是,它可以表示其中的許多約束,並且此練習有助於展示約束如何運作。提供的範例說明了 JSON Schema 的概念,而不是真正的 fstab 檔案的工作 schema。

此範例顯示了檔案系統掛載點的 JSON Schema 表示法,如 /etc/fstab 檔案中所表示。

fstab 檔案中的 entry 可以有多種不同的形式; 這是一個範例

資料
{ "/": { "storage": { "type": "disk", "device": "/dev/sda1" }, "fstype": "btrfs", "readonly": true }, "/var": { "storage": { "type": "disk", "label": "8f3ba6f4-5c70-46ec-83af-0d5434953e5f" }, "fstype": "ext4", "options": [ "nosuid" ] }, "/tmp": { "storage": { "type": "tmpfs", "sizeInMB": 64 } }, "/var/www": { "storage": { "type": "nfs", "server": "my.nfs.server", "remotePath": "/exports/mypath" } }}

建立 fstab schema

我們將從一個基本的 JSON Schema 開始,表達以下約束

  • entry 的清單是一個 JSON 物件;
  • 此物件的成員名稱(或屬性名稱)必須都是有效的絕對路徑;
  • 必須有根檔案系統的 entry(即,/)。

從上到下建構我們的 JSON Schema

  • $id 關鍵字。
  • $schema 關鍵字。
  • type 驗證關鍵字。
  • required 驗證關鍵字。
  • properties 驗證關鍵字。
    • / 金鑰現在是空的; 我們稍後再填寫。
  • patternProperties 驗證關鍵字。
    • 這會透過正規表示式比對其他屬性名稱。 注意:它不比對 /
    • ^(/[^/]+)+$ 金鑰現在是空的; 我們稍後再填寫。
  • additionalProperties 驗證關鍵字。
    • 這裡的值為 false,以約束物件屬性為 / 或符合正規表示式。

您會注意到,正規表示式是明確錨定的(使用 ^$):在 JSON Schema 中,正規表示式(在 patternPropertiespattern 中)預設不會錨定。

schema
{ "$id": "https://example.com/fstab", "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "type": "object", "required": [ "/" ], "properties": { "/": {} }, "patternProperties": { "^(/[^/]+)+$": {} }, "additionalProperties": false}

開始建立 entry schema

我們將從 JSON Schema 的大綱開始,其中會新增一些我們已經展示過的概念。

我們在先前的練習中看過這些關鍵字:$id$schematyperequiredproperties

對此,我們加入:

  • description 註解關鍵字。
  • oneOf 關鍵字。
  • $ref 關鍵字。
    • 在這個例子中,所有使用的參考都是 Schema 本地的,使用相對片段 URI (#/...)。
  • $defs 關鍵字。
    • 包括幾個我們稍後會定義的關鍵名稱。
schema
{ "$id": "https://example.com/entry-schema", "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "description": "JSON Schema for an fstab entry", "type": "object", "required": [ "storage" ], "properties": { "storage": { "type": "object", "oneOf": [ { "$ref": "#/$defs/diskDevice" }, { "$ref": "#/$defs/diskUUID" }, { "$ref": "#/$defs/nfs" }, { "$ref": "#/$defs/tmpfs" } ] } }, "$defs": { "diskDevice": {}, "diskUUID": {}, "nfs": {}, "tmpfs": {} }}

約束一個 entry

現在讓我們擴展這個骨架,為一些屬性新增限制。

  • 我們的 fstype 鍵使用 enum 驗證關鍵字。
  • 我們的 options 鍵使用以下:
    • type 驗證關鍵字(見上文)。
    • minItems 驗證關鍵字。
    • 關於 items 驗證關鍵字。
    • 關於 uniqueItems 驗證關鍵字。
    • 它們共同表示:options 必須是一個陣列,其中的項目必須是字串,至少要有一個項目,而且所有項目都應該是唯一的。
  • 我們有一個 readonly 鍵。

加入這些限制後,schema 現在看起來像這樣

schema
{ "$id": "https://example.com/entry-schema", "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "description": "JSON Schema for an fstab entry", "type": "object", "required": [ "storage" ], "properties": { "storage": { "type": "object", "oneOf": [ { "$ref": "#/$defs/diskDevice" }, { "$ref": "#/$defs/diskUUID" }, { "$ref": "#/$defs/nfs" }, { "$ref": "#/$defs/tmpfs" } ] }, "fstype": { "enum": [ "ext3", "ext4", "btrfs" ] }, "options": { "type": "array", "minItems": 1, "items": { "type": "string" }, "uniqueItems": true }, "readonly": { "type": "boolean" } }, "$defs": { "diskDevice": {}, "diskUUID": {}, "nfs": {}, "tmpfs": {} }}

diskDevice 定義

這裡引入了一個新的關鍵字

  • pattern 驗證關鍵字指出 device 鍵必須是一個以 /dev 開頭的絕對路徑。
資料
{ "diskDevice": { "properties": { "type": { "enum": [ "disk" ] }, "device": { "type": "string", "pattern": "^/dev/[^/]+(/[^/]+)*$" } }, "required": [ "type", "device" ], "additionalProperties": false }}

diskUUID 定義

這裡沒有引入新的關鍵字。

我們有一個新的鍵:label,而且 pattern 驗證關鍵字表示它必須是一個有效的 UUID。

資料
{ "diskUUID": { "properties": { "type": { "enum": [ "disk" ] }, "label": { "type": "string", "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" } }, "required": [ "type", "label" ], "additionalProperties": false }}

nfs 定義

我們發現另一個新的關鍵字

  • format 註解與斷言關鍵字。
資料
{ "nfs": { "properties": { "type": { "enum": [ "nfs" ] }, "remotePath": { "type": "string", "pattern": "^(/[^/]+)+$" }, "server": { "type": "string", "oneOf": [ { "format": "hostname" }, { "format": "ipv4" }, { "format": "ipv6" } ] } }, "required": [ "type", "server", "remotePath" ], "additionalProperties": false }}

tmpfs 定義

我們最後的定義引入了兩個新的關鍵字

  • minimum 驗證關鍵字。
  • maximum 驗證關鍵字。
  • 總之,這些要求大小必須介於 16 到 512 之間,包含 16 和 512。
資料
{ "tmpfs": { "properties": { "type": { "enum": [ "tmpfs" ] }, "sizeInMB": { "type": "integer", "minimum": 16, "maximum": 512 } }, "required": [ "type", "sizeInMB" ], "additionalProperties": false }}

完整的 entry schema

產生的結構描述相當龐大

schema
{ "$id": "https://example.com/entry-schema", "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "description": "JSON Schema for an fstab entry", "type": "object", "required": [ "storage" ], "properties": { "storage": { "type": "object", "oneOf": [ { "$ref": "#/$defs/diskDevice" }, { "$ref": "#/$defs/diskUUID" }, { "$ref": "#/$defs/nfs" }, { "$ref": "#/$defs/tmpfs" } ] }, "fstype": { "enum": [ "ext3", "ext4", "btrfs" ] }, "options": { "type": "array", "minItems": 1, "items": { "type": "string" }, "uniqueItems": true }, "readonly": { "type": "boolean" } }, "$defs": { "diskDevice": { "properties": { "type": { "enum": [ "disk" ] }, "device": { "type": "string", "pattern": "^/dev/[^/]+(/[^/]+)*$" } }, "required": [ "type", "device" ], "additionalProperties": false }, "diskUUID": { "properties": { "type": { "enum": [ "disk" ] }, "label": { "type": "string", "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" } }, "required": [ "type", "label" ], "additionalProperties": false }, "nfs": { "properties": { "type": { "enum": [ "nfs" ] }, "remotePath": { "type": "string", "pattern": "^(/[^/]+)+$" }, "server": { "type": "string", "oneOf": [ { "format": "hostname" }, { "format": "ipv4" }, { "format": "ipv6" } ] } }, "required": [ "type", "server", "remotePath" ], "additionalProperties": false }, "tmpfs": { "properties": { "type": { "enum": [ "tmpfs" ] }, "sizeInMB": { "type": "integer", "minimum": 16, "maximum": 512 } }, "required": [ "type", "sizeInMB" ], "additionalProperties": false } }}

fstab schema 中參考 entry schema

回到原點,我們使用 $ref 關鍵字,將我們的條目結構描述新增到練習開始時留空的鍵中。

  • / 鍵。
  • ^(/[^/]+)+$ 鍵。
schema
{ "$id": "https://example.com/fstab", "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "type": "object", "required": [ "/" ], "properties": { "/": { "$ref": "https://example.com/entry-schema" } }, "patternProperties": { "^(/[^/]+)+$": { "$ref": "https://example.com/entry-schema" } }, "additionalProperties": false}

需要協助嗎?

您覺得這些文件有幫助嗎?

幫助我們改進文件!

在 JSON Schema,我們重視文件貢獻,如同其他類型的貢獻一樣!

仍然需要協助嗎?

學習 JSON Schema 通常令人困惑,但別擔心,我們在這裡提供協助!