JSON Schema
https://json-schema.org/draft/2020-12/schema
MIME:
application/schema+json
https://www.schemastore.org/json/
该网站记录了常见格式的JSON Schema.
- anyOf: 符合数组中的任何一个Schema, 解析器在发现第一个符合条件的Schema后就会结束.
- oneOf: 只符合数组中的一个Schema, 解析器会校验每一个Schema, 确保只有一个Schema符合条件.
- allOf: 符合数组中的所有Schema.
- not: 不满足此子Schema.
在使用逻辑子模式时, 如果当前对象已经包含了其他字段, 则会将这些字段视作共同条件.
{ "type": "number", "oneOf": [ { "multipleOf": 5 } , { "multipleOf": 3 } ]}
等价于
{ "oneOf": [ { "type": "number", "multipleOf": 5 } , { "type": "number", "multipleOf": 3 } ]}
一个URI, 用于标记此JSON的格式, 本身也是一个Schema.
该属性用于标记使用的JSON Schema版本, 代码编辑器依此获得自动完成的提示.
该属性用于标记使用的JSON Schema版本, 代码编辑器依此获得自动完成的提示.
此JSON Schema的URI标识符, 它只是作为标识符使用, 不一定可以在网络上访问.
尽管大多数
对于支持网络的解析器, 如果Schema使用相对URI, 则会根据该JSON文件所处的URI生成它的绝对URI.
$id
字段的值会使用绝对URI, 但 $id
有时也用 /
开头的相对URI.对于支持网络的解析器, 如果Schema使用相对URI, 则会根据该JSON文件所处的URI生成它的绝对URI.
如果一个Schema没有
如果该JSON文件在网络上, 则会将JSON文件的URI当作该Schema的
$id
字段, 意味着它是匿名的.如果该JSON文件在网络上, 则会将JSON文件的URI当作该Schema的
$id
.- title: 该内容的名称,
string
. - description: 该内容的描述,
string
. - type: 该Schema的类型, 必须是JSON类型中的一种或多种,
string | string[]
. - default: 默认值, 通常是被表单生成器使用, 值的类型取决于该内容的类型.
- deprecated: 表示该Schema预定被弃用, 将在未来版本移除,
boolean
. - $comment: Schema作者专用的注释字段, 不会显示给普通用户.
- readOnly:
boolean
, 如果为真, 表示该值不能被应用程序写入, 应用程序发起的相关修改会被拒绝或忽略. - writeOnly:
boolean
, 如果为真, 表示该值不能被应用程序读取, 它可以在更新时被写入, 但应用程序无法看到它.
readOnly和writeOnly在语义上具有排他性, 但JSON Schema的设计者似乎不这么想, 此事实导致这两个字段同时使用会带来混乱, 不建议使用.
- properties: 该对象字段的schema,
Record<string, Schema>
. - required: 该对象必要的字段,
string[]
- items: 该数组元素的Schema.
元组通过
prefixItems
间接实现, 此方式允许数据超出元组所需的元素数量.{ "type": "array", "prefixItems": [ { "type": "number" } , { "type": "string" } , { "enum": ["Street", "Avenue", "Boulevard"] } , { "enum": ["NW", "NE", "SW", "SE"] } ]}
{ "enum": ["red", "green", "blue"]}
表示Schema是一个常数.
{ "const": "Hello World"}
$ref
字段被来引用其他的JSON文件.字段的值为URI, URI应与被引用文件的
$id
值相符.使用相对URI时, 是相对于当前的Base URI.
引用同一个命名空间下的Schema时, 通常会使用以
/
开头的相对URI或绝对URI.对于在
$defs
里定义的Schema, 需要以 #/$defs/
为URI前缀来引用.$ref
支持递归自身, 只需要将值设置为 #
.可以通过锚点来访问一个JSON Schema的子模式:
意味着访问address文件里定义的根据JSON路径
https://example.com/schemas/address#/properties/street_address
意味着访问address文件里定义的根据JSON路径
/properties/street_address
找到的模式.表示此字段依赖于其他字段, 如果没有其他字段, 则此字段不被允许使用.
以下Schema里, credit_card依赖于billing_address字段, 如果只提供credit_card字段, 则会验证失败:
{ "type": "object", "properties": { "name": { "type": "string" } , "credit_card": { "type": "number" } , "billing_address": { "type": "string" } }, "dependentRequired": { "credit_card": ["billing_address"] }}
比dependentRequired更进一步, 不仅是依赖字段, 还依赖字段符合特定的Schema.
credit_card依赖于billing_address字段, 且billing_address字段必须是一个字符串:
{ "type": "object", "properties": { "name": { "type": "string" } , "credit_card": { "type": "number" } }, "dependentSchemas": { "credit_card": { "properties": { "billing_address": { "type": "string" } } , "required": ["billing_address"] } }}
根据if-then-else分支语句来决定要使用哪个子Schema.
单个条件语句(如果未提供country字段, 也会落入else分支):
{ "type": "object", "properties": { "street_address": { "type": "string" } , "country": { "enum": ["USA", "Canada"] } }, "if": { "properties": { "country": { "const": "USA" } } }, "then": { "properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } } }, "else": { "properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } } }}
可翻译为:
if (this.country === 'USA') { assert(this.postal_code.match(/[0-9]{5}(-[0-9]{4})?/))} else { assert(this.postal_code.match(/[A-Z][0-9][A-Z] [0-9][A-Z][0-9]/))}
组合多个条件语句(会编写出反直觉和难以阅读的模式, 因此不推荐使用),
后两个if里的required字段是必要的, 不可省略:
后两个if里的required字段是必要的, 不可省略:
{ "type": "object", "properties": { "street_address": { "type": "string" } , "country": { "enum": ["USA", "Canada", "Netherlands"] } }, "allOf": [ { "if": { "properties": { "country": { "const": "USA" } } } , "then": { "properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } } } } , { "if": { "properties": { "country": { "const": "Canada" } } , "required": ["country"] } , "then": { "properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } } } } , { "if": { "properties": { "country": { "const": "Netherlands" } } , "required": ["country"] } , "then": { "properties": { "postal_code": { "pattern": "[0-9]{4} [A-Z]{2}" } } } } ]}
可翻译为:
if (this.country === 'USA') { assert(this.postal_code.match(/[0-9]{5}(-[0-9]{4})?/))} else if (this.country === 'Canada') { assert(this.postal_code.match(/[A-Z][0-9][A-Z] [0-9][A-Z][0-9]/))} else if (this.country === 'Netherlands') { assert(this.postal_code.match(/[0-9]{4} [A-Z]{2}/))} else { assert(this.postal_code.match(/[0-9]{5}(-[0-9]{4})?/)) // USA的模式}
在过去的版本里是
definitions
.定义创建可以被引用的内部项,
项的键是被引用项的URI标识符.
Map<string, Schema>
,项的键是被引用项的URI标识符.
不太常用的字段, 可以主动定义子模式的名称, 从而被
值需要以
$ref
引用.值需要以
#
开头, 例如 { $anchor: "#street_address" }
可以在string类型的Schema里表示多媒体内容,
为此需要将
为此需要将
contentMediaType
字段设置为多媒体内容的MIME类型.contentEncoding
字段代表多媒体的编码, 最常用的是 base64
.很多JSON Schema工具都不能处理引用的外部资源,
一种解决方法是将这些外部资源打包成一个JSON文件.
一种解决方法是将这些外部资源打包成一个JSON文件.
实际的打包是将
$ref
的外部文件以 $defs
的形式定义在同一个文件内来实现的.