具体类型定义
JSON Schema中用type关键字来描述数据的类型,定义了6种基本数据类型:
type关键字可以用字符串或者数组来描述。字符串从以上6种数据类型中取值;数组必须由以上6种数据类型的字符串组成,表明type可以是数组中表示的任意数据类型。
string
string为字符串类型。
{ "type": "string" }
"Hello" // OK
"" // OK
"10" // OK
10 // WRONG!
另外,可以用一些关键字辅助type进行类型校验,关键字与type平级。
Length
用minLength和maxLength关键字描述字符串的最小和最大长度,对应值为非负整数。
{
"type": "string",
"minLength": 2,
"maxLength": 3
}
"Hello" // WRONG!
"Hi" // OK
Regular Expressions
用pattern关键字可以正则描述字符串内容,具体语法见regular expression syntax章节。
{
"type": "string",
"pattern": "^He"
}
"Hello" // OK
"Hi" // WRONG!
"say Hello" // WRONG!
Format
用format关键字用于描述字符串的格式,默认为注释,不具有校验规则。
format与validator组合使用可以用于校验字符串的格式,使format可以作为断言而不仅是注释。
format有内置的类型定义:
- Dates and times
"date-time"用于表示例如:2018-11-13T20:20:39+00:00
"time"用于表示例如:20:20:39+00:00
"date"用于表示例如:2018-11-13
"duration"用于表示一段时间,例如P3D可以表示3天的时间。
- Email addresses
"email"
"idn-email"
- Hostnames
"hostname"
"idn-hostname"
- IP Addresses
"ipv4"
"ipv6"
- Resource identifiers
"uuid"
"uri"
"uri-reference"
"iri"
"iri-reference"
- URI template
"uri-template"
- JSON Pointer
"json-pointer"
"relative-json-pointer"
- Regular Expressions
"regex"
numeric types
integer
integer用于表示整型数字。JSON没有区分整型和浮点型的具体类型,所以有没有小数点不能作为JSON中判断是否是整型的依据。
{ "type": "integer" }
42 // OK
-1 // OK
1.0 // OK
3.14 // WRONG!
"42" // WRONG!
number
number用于表示任意数字,包括整型和浮点型。
{ "type": "number" }
42 // OK
-1 // OK
1.0 // OK
3.14 // OK
"42" // WRONG!
Multiples
multipleOf关键字用于限制数字为给定数字的倍数,给定数字必须是任意正数。
{
"type": "number",
"multipleOf": 10
}
0 // OK
20 // OK
21 // WRONG!
{
"type": "number",
"multipleOf" : 0.01
}
4.02 // OK
4.021 // WRONG!
Range
minimum和maximum关键字用于限制数字的范围,exclusiveMinimum和exclusiveMaximum关键字用于排除边界的范围限制。
x ≥
minimum
x >exclusiveMinimum
x ≤maximum
x <exclusiveMaximum
这些限制条件可以组合使用,且都会生效。
在JSON Draft 4中(我们没有使用),exclusiveMinimum和exclusiveMaximum关键字的值为true或者false,表示是否排除最大/最小边界。
object
object是JSON中的映射类型,将"keys"映射到"values","keys"必须是字符串,每一对通常指一个“属性”。
Properties
properties关键字用于描述一系列属性。properties本身是object类型,对象中的每一个key都是属性名,每一个value都是用于描述该属性的schema. 任何在properties中与属性名不匹配的关键字都会被忽略。
{
"type": "object",
"properties": {
"number": { "type": "number" },
"street_name": { "type": "string" },
"street_type": { "enum": ["Street", "Avenue", "Boulevard"] }
}
}
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" } // OK
{ "number": "1600", "street_name": "Pennsylvania", "street_type": "Avenue" } // WRONG!
{ "number": 1600, "street_name": "Pennsylvania" } // OK
{ } // OK
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" } // OK
Pattern Properties
patternProperties是用于描述属性名匹配为正则模式的关键字,如果关键字下描述的属性名能够匹配,则会有对应的schema校验。
Additional Properties
additionalProperties关键字用于描述不在properties下或不在patternProperties下的额外属性,value为用于描述额外属性的schema.
将addtionalProperties的值直接设置为false表示不允许任何额外属性。
{
"type": "object",
"properties": {
"number": { "type": "number" },
"street_name": { "type": "string" },
"street_type": { "enum": ["Street", "Avenue", "Boulevard"] }
},
"additionalProperties": false
}
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" } // OK
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" } // WRONG!
也可以用schema来描述额外属性的数据格式。
{
"type": "object",
"properties": {
"number": { "type": "number" },
"street_name": { "type": "string" },
"street_type": { "enum": ["Street", "Avenue", "Boulevard"] }
},
"additionalProperties": { "type": "string" }
}
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" } // OK
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" } // OK
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "office_number": 201 } // WRONG!
properties和patternProperties也可以与addtionalProperties组合使用。
Unevaluated Properties
unevaluatedProperties的作用与additionalProperties基本一致,区别在于unevaluatedProperties可以识别子模式中声明的属性。也就是说,unevaluatedProperties捕获的是未被其它属性模式捕获的属性。
{
"type": "object",
"properties": {
"street_address": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" },
"type": { "enum": ["residential", "business"] }
},
"required": ["street_address", "city", "state", "type"],
"if": {
"type": "object",
"properties": {
"type": { "const": "business" }
},
"required": ["type"]
},
"then": {
"properties": {
"department": { "type": "string" }
}
},
"unevaluatedProperties": false
}
{
"street_address": "1600 Pennsylvania Avenue NW",
"city": "Washington",
"state": "DC",
"type": "business",
"department": "HR"
} // OK
{
"street_address": "1600 Pennsylvania Avenue NW",
"city": "Washington",
"state": "DC",
"type": "residential",
"department": "HR"
} // WRONG!
Required Properties
required关键字表示properties中必须出现的属性名列表,描述required的数据类型为由字符串组成的数组。
Property names
propertyNames可以用于以正则校验属性名格式。由于对象keys不论如何必须是字符串类型,因此在声明propertyNames默认含有{ "type": "string" }规则。
Size
minProperties和maxProperties可以用于限制一个对象中的属性个数,给定的数字必须是正整数。
array
对于数组有2种验证方式:
- 列表验证:用于描述匹配相同schema的任意长度序列;
- 元组验证:用于描述匹配不同schema的固定长度序列。
Items
items用于描述数组中所有元素都要满足的schema,数组可以是任意长度的。
Tuple validation
prefixItems用于验证固定长度和模式的数组。描述prefixItems的数据类型为数组,其中每一个元素都是一个对象,第一个对象描述数组中第一个元素的数据模式,第二个对象描述数组中第二个元素的数据模式,以此类推。
{
"type": "array",
"prefixItems": [
{ "type": "number" },
{ "type": "string" },
{ "enum": ["Street", "Avenue", "Boulevard"] },
{ "enum": ["NW", "NE", "SW", "SE"] }
]
}
[1600, "Pennsylvania", "Avenue", "NW"] // OK
[10, "Downing", "Street"] // OK
[24, "Sussex", "Drive"] // WRONG!
["Palais de l'Élysée"] // WRONG!
Additional Items
items可以用于描述未在prefixItems中描述的额外元素的数据模式。
Unevaluated Items
unevaluatedItems关键字作用与Items基本一致,区别在于items不能识别子模式中的数据模式,会直接忽略allOf,anyOf, 或者oneOf中的子模式;而unevaluatedItems会校验子模式。
{
"allOf": [
{ "prefixItems": [
{ "type": "boolean" },
{ "type": "string" }
] }
],
"items": { "const": 2 }
}
[true, "a", 2] // WRONG!
{
"allOf": [
{ "prefixItems": [
{ "type": "boolean" },
{ "type": "string" }
] }
],
"unevaluatedItems": { "const": 2 }
}
[true, "a", 2] // OK
Contains
contains用于校验数组中一个或多个元素的数据模式,只要数组中有一个元素满足contains中的模式,就可以通过校验。
{
"type": "array",
"contains": {
"type": "number"
}
}
["life", "universe", "everything", 42] // OK
["life", "universe", "everything", "forty-two"] // WRONG!
[1, 2, 3, 4, 5] // OK
minContains / maxContains
minContains和maxContains用于描述数组中满足contains描述数据模式的个数限制。
Length
minItems和maxItems关键字用于限制数组中元素的总个数。
Uniqueness
uniqueItems关键字用于描述数组中的元素是否是独一无二的。
{
"type": "array",
"uniqueItems": true
}
[1, 2, 3, 4, 5] // OK
[1, 2, 3, 3, 4] // WRONG!
boolean
boolean只接受2个特定值:true和false,其余值例如1和0都不会被接受。
null
当数据类型type被定义为null时,代表只接受null值,空值不包含在内。
Enumerated values
enum关键字用于限制取值在给出的固定取值集合中,enum的value必须为至少有1个元素的数组,且每个元素都必须是独一无二的。
{
"enum": ["red", "amber", "green", null, 42]
}
"red" // OK
null // OK
42 // OK
0 // WRONG!
Constant values
const关键字用于限制取值为给定的值。
{
"properties": {
"country": {
"const": "United States of America"
}
}
}
{ "country": "United States of America" } // OK
{ "country": "Canada" } // WRONG!
regular expression syntax
Schema Composition
JSON Schema囊括了一些可以把schema组合到一起共同描述复杂schema结构的关键字,结合这些关键字可以让一个值被多条规则同时校验。这些关键字对应于众所周知的boolean代数概念如AND, OR, XOR和NOT.
这些用于组合schema的关键字是:
allOf: (AND)必须满足所有涉及子模式anyOf: (OR)必须满足任意一个涉及子模式oneOf: (XOR)必须满足正好一个涉及子模式
以上所有关键字必须被组合到一个数组,每一个元素是一个schema. 递归模式会成倍增加处理时间。
另外,
not: (NOT)必须不能满足给定的schema
在组合这些关键字时,非常容易出现互相矛盾的描述,导致无法通过校验,注意不要产生自相矛盾的逻辑。
allOf
验证allOf时,会验证所有给定的子模式。
{
"allOf": [
{ "type": "string" },
{ "maxLength": 5 }
]
}
"short" // OK
"too long" // WRONG!
注意allOf中的子模式不能互相有继承、依赖关系,实例必须独立地满足allOf中的所有schema.
anyOf
验证anyOf时,会验证通过一个或多个给定的子模式。
{
"anyOf": [
{ "type": "string", "maxLength": 5 },
{ "type": "number", "minimum": 0 }
]
}
"short" // OK
"too long" // WRONG!
12 // OK
-5 // WRONG!
oneOf
验证oneOf时,只能验证通过有且仅有一个给定的子模式。
{
"oneOf": [
{ "type": "number", "multipleOf": 5 },
{ "type": "number", "multipleOf": 3 }
]
}
10 // OK
9 // OK
2 // WRONG!
15 // WRONG!
not
验证not时,会验证不通过所有给定的子模式。
{ "not": { "type": "string" } }
42 // OK
{ "key": "value" } // OK
"I am a string" // WRONG!
dependentRequired
dependentRequired关键字描述key属性存在时,value中的属性也必须给出;key属性不存在时,value中的属性则不作要求这样的数据模式。dependentRequired以object描述,每一个key属性的value以array描述。
以下面的schema为例,描述了credit_card存在时,必须有billing_address作为寄送信用卡的地址;credit_card不存在时,则对billing_address不作要求:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"credit_card": { "type": "number" },
"billing_address": { "type": "string" }
},
"required": ["name"],
"dependentRequired": {
"credit_card": ["billing_address"]
}
}
{
"name": "John Doe",
"credit_card": 5555555555555555,
"billing_address": "555 Debtor's Lane"
} // OK
{
"name": "John Doe",
"credit_card": 5555555555555555
} // WRONG
{
"name": "John Doe",
"billing_address": "555 Debtor's Lane"
} // OK
dependentSchemas
dependentSchemas关键字描述key属性存在时,需要满足的子模式。子模式schema与allOf校验规则相同。
Draft 2019-09之前,dependentRequired和dependentSchemas都是同样的关键字dependencies. 如果对应值是一个数组,功能就类似dependentRequired,如果对应值是一个schema, 功能就类似dependentSchema.
If-Then-Else
if, then和else关键字允许子模式根据另一个schema的校验结果生效。
| if | then | else | whole schema |
|---|---|---|---|
| T | T | n/a | T |
| T | F | n/a | F |
| F | n/a | T | T |
| F | n/a | F | F |
| n/a | n/a | n/a | T |
Annotations
JSON Schema包括了一些不会用于校验的关键字,这些关键字用于描述一部分schema. 这些类似“注释”的关键字都不是必需的,但鼓励用户在设计过程中使用,增强可读性。
注释类的关键字可以被用在任意模式或子模式中,且同一关键字在同一层只能使用一次。
title和description必须是字符串。title要尽可能的简短,而description则提供关于这部分schema描述内容的详细说明。default表示一个默认值,这个值不会在验证过程中自动填充,而是作为建议给用户进行说明。default表示的值应当与值缺失时自动填充的值一致。examples表示一个例子组成的数组用于给出符合schema的例子。这个字段不会用于校验,但是可以给后续阅读者反应这段schema的用途。readOnly和writeOnly一般用于API上下文中,用于表示该值仅用于读/写。$comment用于给schema文件添加评论。
$schema
$schema关键字用于声明该schema是用哪个版本的JSON Schema写的。$schema关键字的值也可以用来作为判断校验schema的版本的依据,一般作用于整篇文档,必须放在根目录。