入门

使用 JSON 模式对文件系统建模

在本循序渐进的指南中,您将学习如何设计一个 JSON 模式来反映 /etc/fstab 文件的结构。

本指南分为以下几节:

简介

并非所有 fstab 文件的约束都可以单独使用 JSON 模式进行建模;然而,它可以很好地表示其中很大一部分,并且该练习有助于演示约束的工作原理。提供的示例用于说明 JSON 模式概念,而不是 fstab 文件的实际工作模式。

此示例显示了文件系统挂载点的 JSON 模式表示,如 /etc/fstab 文件中所示。

fstab 文件中的条目可以有多种不同形式;这是一个示例

数据
{ "/": { "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 模式

我们将从表达以下约束的基本 JSON 模式开始

  • 条目列表是一个 JSON 对象;
  • 此对象的成员名称(或属性名称)必须都是有效的绝对路径;
  • 必须有一个根文件系统的条目(即 /)。

从上到下构建我们的 JSON 模式

  • $id 关键字。
  • $schema 关键字。
  • type 验证关键字。
  • required 验证关键字。
  • properties 验证关键字。
    • / 键现在为空;我们稍后会填写它。
  • patternProperties 验证关键字。
    • 这通过正则表达式匹配其他属性名称。注意:它不匹配 /
    • ^(/[^/]+)+$ 键现在为空;我们稍后会填写它。
  • additionalProperties 验证关键字。
    • 这里的值是 false,以将对象属性约束为 / 或匹配正则表达式。

您会注意到正则表达式是显式锚定的(使用 ^$):在 JSON 模式中,正则表达式(在 patternPropertiespattern 中)默认情况下不锚定。

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

启动 entry 模式

我们将从 JSON 模式的概要开始,该模式将新概念添加到我们已经演示的内容中。

我们在之前的练习中看到了这些关键字:$id$schematyperequiredproperties

我们添加了

  • description 注解关键字。
  • oneOf 关键字。
  • $ref 关键字。
    • 在这种情况下,所有使用的引用都是使用相对片段 URI(#/...)在模式本地的。
  • $defs 关键字。
    • 包括几个我们稍后将定义的键名。
模式
{ "$id": "https://example.com/entry-schema", "$schema": "https://json-schema.fullstack.org.cn/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": {} }}

约束条目

现在让我们扩展这个框架,为某些属性添加约束。

  • 我们的 fstype 键使用 enum 验证关键字。
  • 我们的 options 键使用以下内容
    • type 验证关键字(见上文)。
    • minItems 验证关键字。
    • items 验证关键字。
    • uniqueItems 验证关键字。
    • 这些一起表示:options 必须是一个数组,其中的项必须是字符串,必须至少有一个项,并且所有项都应该是唯一的。
  • 我们有一个 readonly 键。

添加了这些约束后,模式现在看起来像这样

模式
{ "$id": "https://example.com/entry-schema", "$schema": "https://json-schema.fullstack.org.cn/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 之间(含)。
数据
{ "tmpfs": { "properties": { "type": { "enum": [ "tmpfs" ] }, "sizeInMB": { "type": "integer", "minimum": 16, "maximum": 512 } }, "required": [ "type", "sizeInMB" ], "additionalProperties": false }}

完整的条目模式

最终的 schema 相当大

模式
{ "$id": "https://example.com/entry-schema", "$schema": "https://json-schema.fullstack.org.cn/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 模式中引用 entry 模式

我们兜了一圈,使用 $ref 关键字将我们的入口 schema 添加到练习开始时留空的键中

  • / 键。
  • ^(/[^/]+)+$ 键。
模式
{ "$id": "https://example.com/fstab", "$schema": "https://json-schema.fullstack.org.cn/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 通常会让人感到困惑,但别担心,我们将随时为您提供帮助!