上篇文章主要介绍了JSON Schema的标准、规范、实现(),接下来本文重点介绍JSON Schema的基本概念、使用。
三、快速开始
- 官网链接:http://json-schema.org/learn/ 、http://json-schema.org/understanding-json-schema/
- json schema在线校验工具:https://jsonschemalint.com/
- json schema在线生成功能:https://json-schema-inferrer.herokuapp.com/ 、https://hellosean1025.github.io/json-schema-visual-editor/
- json格式化、压缩、转义在线工具:https://www.bejson.com/
1、what is schema?
如果您曾经使用过XML Schema,RelaxNG或ASN.1,则可能已经知道什么是schema。要了解JSON Schema,首先要是知道什么事JSON。JSON代表“ JavaScript对象表示法”,一种简单的数据交换格式。它最初是作为万维网的一种表示法,由于大多数网络浏览器中都存在JavaScript,并且JSON基于JavaScript,因此很容易在其中进行支持。js的基本数据类型:
- object:{ "key1": "value1", "key2": "value2" }
- array:["a","b"]
- number:1、1.2
- string:“string”
- boolean:true、false
- null:null
利用这些简单的数据类型,可以表示各种结构化数据。但是,由于其灵活性,导致同一概念可以以多种方式表示。例如:
{
  "name": "George Washington",
  "birthday": "February 22, 1732",
  "address": "Mount Vernon, Virginia, United States"
}
{
  "first_name": "George",
  "last_name": "Washington",
  "birthday": "1732-02-22",
  "address": {
    "street_address": "3200 Mount Vernon Memorial Highway",
    "city": "Mount Vernon",
    "state": "Virginia",
    "country": "United States"
  }
}以上两种写法表达了同一个信息。记录的设计将在很大程度上取决于其在应用程序中的预期用途,因此这里没有正确或错误的答案。但是,当应用程序说“给我一个人的JSON记录”时,准确知道该记录的组织方式非常重要。例如,我们需要知道需要哪些字段以及如何表示值。这就是JSON Schema的来源。
2、基础篇
2.1)特殊的schema:
在JSON Schema中,一个空对象({})是一个有效的schema,它可以兼容所有的json;同样也可以使用true代替空对象来表示匹配任何内容的schema,或者使用false表示不匹配任何内容的schema。例如:
//schema 可以匹配一下所有json
{}
//json
42
"string"
{"a":1}
//同样,true也可以匹配上面所有的json2.2)声明json schema:
由于JSON Schema本身就是JSON,因此很难分辨出什么是JSON Schema或只是任意JSON块。 $ schema关键字用于声明某些内容为JSON模式。最好将其包括在内,尽管不是必需的。例如:
{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "properties": {
    
}2.3)keyword:
| 关键字 | 描述 | 
| $schema | 表示该JSON Schema使用的版本规范,非必填,目前最新一版“Draft-07”是2019.09发布的。每个版本的语法可能有出入,方便以后人员维护建议使用 | 
| title | JSON Schema文件的标题,非必填 | 
| description | JSON Schema文件的描述信息,非必填 | 
| type | 待校验元素的类型(例如,最外层的type表示待校验的是一个JSON对象,内层type分别表示待校验的元素类型为,可以是object、array、null、number,string,array,object) | 
| properties | JSON对象中,各个key-value对中value的限制条件 | 
| required | 校验的JSON对象中,必须存在的key,不存在则校验失败 | 
注:type可以使用数组表示,表示多种类型。例如:
{ "type": "number" }
 42 //√
 42.0  //√
 "42"  //×
{ "type": ["number", "string"] }
 42 //√
 42.0  //√
 "42"  //√接下里来,具体看下每种类型的具体使用。
3、JSON Schema 语法:
3.1)string类型:
用来约束json数据中value的类型,此外还可以通过一些属性来具体约束value的长度、正则...
1)minLength、maxLength:
{
  "type": "string",
  "minLength": 2,
  "maxLength": 3
}
"A"  //×
"ABCD"  //×
"ABC"  //√2)正则表达式:
正则表达式语法是JavaScript(特别是ECMA 262)中定义的语法。具体可以查看:http://json-schema.org/understanding-json-schema/reference/regular_expressions.html#regular-expressions
{
   "type": "string",
   "pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$"
}
"555-1212"  //√
"(888)555-1212 ext. 532"  //×3)Format:
不常用,值只能是以下的取值date-time(时间格式)、email(邮件格式)、hostname(网站地址格式)、ipv4、ipv6、uri、uri-reference、uri-template、json-pointer。假如要校验的字符串是邮箱格式的可以使用"forma":"email",而不用pattern自己去指定正则表达式。
3.2)integer、number类型:
integer表示整型,number表示浮点型数据。
注:对“整数”类型的精确处理可能取决于JSON Schema验证程序的实现,JavaScript(以及JSON)没有整数和浮点值的不同类型。因此,JSON Schema不能单独使用类型来区分整数和非整数。JSON Schema规范建议(但不要求)验证者使用数学值确定数字是否为整数,而不是单独的类型。因此,在这一点上,验证者之间存在一些分歧。例如,基于JavaScript的验证器可以接受1.0作为整数,而基于Python的jsonschema不接受。
1)multipleOf:
可以使用关键字multipleOf将数字限制为给定数字的倍数。
{
    "type"       : "number",
    "multipleOf" : 10
}
20  //√
23  //×2)range:
- x ≥ minimum
- x > exclusiveMinimum
- x ≤ maximum
- x < exclusiveMaximum
{
  "type": "number",
  "minimum": 0,
  "exclusiveMaximum": 100
}
-1   //×
100  //×
99  //√3.3)boolean:
{ "type": "boolean" }
true   //√
false  //√
0  //×
"true"  //×3.4)null:
{ "type": "null" }
null   //√
false  //×
0   //×
""  //×3.5)object:
1)properties:
使用properties关键字定义对象上的属性(键值对)。属性的值是一个对象,其中每个键是json数据中的属性名称,每个值是用于验证该属性的JSON Schema。
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "number"
    },
    "name": {
      "type": "string"
    }
  }
}
{}  //√
{"id":1}  //√
{"name":"test"}  //√
{"id":1,"name":"test"}  //√
{"id":1,"name":"test","other":1}  //√可以使用enum指定某个字段的值。例如:
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "number"
    },
    "name": {
      "type": "string",
      "enum": ["a", "b"]
    }
  }
}
{}  //√
{"name":"a"}  //√
{"name":""} //×
{"name":"c"}  //×2)additionalProperties :
additionalProperties关键字用于控制json数据中的字段是否允许超过JSON Schema中定义的字段。默认情况下允许,additionalProperties值可以是布尔型,也可以是对象(用来指定允许哪些类型)
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "number"
    },
    "name": {
      "type": "string"
    }
  },
  "additionalProperties": false
}
{}  //√
{"id":1}  //√
{"name":"test"}  //√
{"id":1,"name":"test"}  //√
{"id":1,"name":"test","other":1}  //×也可以通过additionalProperties控制允许哪些类型的字段,例如:
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "number"
    },
    "name": {
      "type": "string"
    }
  },
  "additionalProperties": false
}
{}  //√
{"id":1}  //√
{"name":"test"}  //√
{"id":1,"name":"test"}  //√
{"id":1,"name":"test","other":"1"}  //√
{"id":1,"name":"test","other":1}  //×3)required:
默认,json数据中的字段可以比JSON Schema中定义的字段多或者少。可以使用additionalProperties 来控制json数据中的字段不能多于JSON Schema中定义的字段;同样,可以使用required控制某些JSON Schema中的字段,必须要在json数据中出现。
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "number"
    },
    "name": {
      "type": "string"
    }
  },
  "required": [
    "name"
  ]
}
{}  //×
{"id":1}  //×
{"name":"test"}  //√
{"id":1,"name":"test"}  //√
{"id":1,"name":"test","other":1}  //√4)Pattern Properties:
additionalProperties 和required可以限制json中的字段是否符合JSON Schema中的定义。可以进一步通过pattern来限制那些符合某些正则的字段。
{
  "type": "object",
  "patternProperties": {
    "^S_": { "type": "string" },
    "^I_": { "type": "integer" }
  },
  "additionalProperties": false
}
{}  //√
{ "S_25": "This is a string" }  //√
{ "I_0": 42 }  //√
{"a":1}  //×
{"b":"b"}  //×5)Property names:
draft6新特性,Property names可以根据schema验证属性的名称,而不管其值、类型如何。如果您不想强制使用特定的属性,但是要确保这些属性的名称遵循特定的约定,这将很有用。
{
  "type": "object",
  "propertyNames": {
    "pattern": "^a"
  }
}
{}  //√
{"a":1}  //√
{"a":"1"}  //√
{"a":{}}  //√
{"a":[]}  //√
{"b":1}  //×6)Property dependencies:
我们使用dependencies关键字表示一个属性对另一个属性的依赖。 dependency关键字的值是一个对象。对象中的每个条目都从属性名p映射到列出存在p时所需的属性的字符串数组。
{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "credit_card": { "type": "number" },
    "billing_address": { "type": "string" }
  },
  "dependencies": {
    "credit_card": ["billing_address"]
  }
}
{"name":"John Doe","credit_card":555,"billing_address":"555 Debtor's Lane"}//√
{"billing_address":"555 Debtor's Lane"}//√
{"credit_card":555}  //×7)Schema dependencies:
Schema dependencies的工作方式类似于Property dependencies,但是它们不仅可以指定其他必需的属性,还可以扩展模式使其具有其他约束。
8)size:
{
  "type": "object",
  "minProperties": 2,
  "maxProperties": 3
}
{ "a": 0, "b": 1 }  //√
{ "a": 0, "b": 1, "c": 2 }  //√
{ "a": 0 }//×
{} //×3.6)array:
{ "type": "array" }
[1, 2, 3, 4, 5]  //√
[3, "different", { "types" : "of values" }] //√1)items:
可以使用items限制数组中元素的类型。
{
  "type": "array",
  "items": {
    "type": "number"
  }
}
[]   //√
[1, 2, 3, 4, 5] //√
[1, 2, "3", 4, 5] //×此外,可以通过items来指定数组中每个元素的类型。(有顺序要求的)
{
  "type": "array",
  "items": [
    {
      "type": "number"
    },
    {
      "type": "string"
    }
  ]
}
[1]  //√
[1,"Pennsylvania"]  //√
[1, "Pennsylvania",1]   //√
["Pennsylvania"]    //×
["Pennsylvania",1]  //×同时,也可以使用additionalItems来限制是否允许其他类型存在。
{
  "type": "array",
  "items": [
    {
      "type": "number"
    },
    {
      "type": "string"
    }
  ],
  "additionalItems": false
}
[1]  //√
[1,"Pennsylvania"]  //√
["Pennsylvania"]    //×
["Pennsylvania",1]  //×
[1, "Pennsylvania",1]   //×2)contains:
draft6新增特性。items是校验数组中每个元素类型,contains用来校验一个或多个元素。
{
   "type": "array",
   "contains": {
     "type": "number"
   }
}
["life", "universe", "everything", 42]  //√
["life", "universe", "everything"] //×3)Tuple validation:
可以使用enum,对数组中每个元素的取值进行校验。例如:
{
  "type": "array",
  "items": [
    {
      "type": "string",
      "enum": ["Street", "Avenue", "Boulevard"]
    },
    {
      "type": "string",
      "enum": ["NW", "NE", "SW", "SE"]
    }
  ]
}
["Avenue", "NW"]  //√
["Avenue", "2NW"] //×4)length:
{
  "type": "array",
  "minItems": 2,
  "maxItems": 3
}
[]  //√
[1,2,]  //√
[1,2,3]    //√
[1,2,3,4]  //×5)uniqueness:
{
  "type": "array",
  "uniqueItems": true
}
[]  //√
[1, 2, 3, 4, 5]  //√
[1, 2, 3, 4, 5, 5] //×4、高级篇:
4.1)combining schemas:
可以使用allOf、anyOf、oneOf、not 将多个JSON Schema组合起来使用,形成具有一定逻辑关系的schema。
{
  "oneOf": [
    { "type": "number", "multipleOf": 5 },
    { "type": "number", "multipleOf": 3 }
  ]
}4.2)reuse:
重用是编程中最核心的思想之一。JSON Schema也可以重用。
1)definitions、$ref:
我们可以将一个JSON Schema放到definitions中,供其他地方重用。可以通过$ref来引用definitions中的schema。(通过JSON Pointer)
2)看一个例子:
{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "address": {
      "type": "object",
      "properties": {
        "street_address": { "type": "string" },
        "city":           { "type": "string" },
        "state":          { "type": "string" }
      },
      "required": ["street_address", "city", "state"]
    }
  },
  "type": "object",
  "properties": {
    "billing_address": { "$ref": "#/definitions/address" },
    "shipping_address": { "$ref": "#/definitions/address" }
  },
  "required": ["shipping_address", "billing_address"]
}
//json
{
  "shipping_address": {
    "street_address": "1600 Pennsylvania Avenue NW",
    "city": "Washington",
    "state": "DC"
  },
  "billing_address": {
    "street_address": "1st Street SE",
    "city": "Washington",
    "state": "DC"
  }
}4.3)Recursion(递归):
$ ref元素可用于创建引用自己的递归模式。例如,您可能具有一个包含多个子级的人员模式,每个子级也是人员实例。
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "person": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "children": {
          "type": "array",
          "items": { "$ref": "#/definitions/person" },
          "default": []
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "person": { "$ref": "#/definitions/person" }
  }
}
//json
{
  "person": {
    "name": "Elizabeth",
    "children": [
      {
        "name": "Charles",
        "children": [
          {
            "name": "William",
            "children": [
              { "name": "George" },
              { "name": "Charlotte" }
            ]
          },
          {
            "name": "Harry"
          }
        ]
      }
    ]
  }
}4.4)$id:
可以使用$id属性指向一个有效的URL。
{ "$id": "http://foo.bar/schemas/address.json" }
                










