JSON Schema的关键字详细介绍

参考文档:

https://json-schema.org/understanding-json-schema/reference/object.html

https://zhuanlan.zhihu.com/p/58516876

JSON Schema简介

JSON与XML相比有很多优势,JSON在各方面中的似有取代XML的趋势。JSON Schema是基于JSON格式的。

JSON Schema是

  • 用于描述现有的数据格式,定义JSON数据结构以及校验JSON数据内容。
  • 丰富的JSON校验格式语法进行定制化开发,验证JSON格式。
  • 可以把JSON Schema理解为数据交换的一种虚拟”合同”,对数据进行一致性检验,保证数据正确的一种手段,所以一般在自动化测试过程中使用JSON Schema进行数据准确性校验。

json schema官网: http://json-schema.org/

json生成schema工具: https://jsonschema.net/#/

JSON Schema在接口自动化测试中发挥着结构和数据校验的角色。

Python中使用JSON Schema

  • 使用pip install jsonschema

Json Schema关键字

$schema、title、description、type、properties、required

Json Schema使用json格式来表示:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "这是title",
    "description": "这是描述信息 ",
    "type": "object",
    "properties": {
        "name": {
            "description": "这是name的描述信息",
            "type": "string"
        }
    },
    "required": [
        "name"
    ]
}

下边来介绍一下各个关键字的含义:

$schema

用于指定JSON Schema的版本信息,draft-07 代表的就是版本,该关键字可以省略,当前最新版本是draft-07,可以在官网http://json-schema.org/中查看更多它的详细说明。

title和description

用来描述JSON每个字段,title一般用来进行简单的描述,而description一般是进行详细的描述信息,这两个关键字都可以省略。可以对最外层的信息进行描述,也可以对JSON中的列表层级、字段值等进行描述。

type

用于约束校验的JSON元素的数据类型,比如最外层的type关键字值为object,校验的JSON数据是一个JSON对象。而name下的type值为string,那么这个第一层级下的key(name)的数据类型为string。如果需要校验的JSON数据中name的类型不为string就会校验失败。

Type其实就是JSON数据的基本数据类型,一般是有6种,加上null一共有7种:

Type取值 对应的Java数据类型:

json type java type
object Java.lang.Object
array Java.util.List
integer Int(java.lang.Integer)
number Float(java.lang.Float)或int
boolean Java.lang.Boolean
string Java.lang.String

JSON Schema从Java的基本数据类型中对JSON结构进行校验,所以对JSON结构的校验可以理解为对每种不同数据类型的相应校验。

对于object类型的关键字

properties、required、minProperties、maxProperties、propertyNames、dependencies、patternProperties、additionalProperties。

properties

指定JSON对象中的各种不同key应该满足的校验逻辑,如果需要校验的JSON对象中所有的值通过了定义的key对应的值,则通过校验。

required

这个关键字是数组,数组中的元素必须是字符串,必须是唯一的。这个关键字限制了JSON数据必须包含的key,需要注意的是required关键字指定的是这一级的key,所以如果有多级的话,那需要在多级里边添加不同的required关键字来标识这个JSON对象必须要包含的key。

minProperties、maxProperties

这两个关键字的值都是非负整数。待校验的JSON对象中一级key的个数限制,minProperties指定了待校验的JSON对象可以接受的最少一级key的个数,maxProperties指定了待校验JSON对象可以接受的最多一级key的个数。

propertyNames

如果待校验JSON对象中的每个一级key都能通过该关键字指定的JSON Schema的校验,那么才认为待校验的JSON对象通过校验。注意,待校验JSON对象的一级key都是string类型。

patternProperties

正则表达式匹配json出现的属性,该JSON对象的每一个一级key都是一个正则表达式,用来匹配value值。

只有待校验JSON对象中的一级key,通过与之匹配的patternProperties中的一级正则表达式,对应的JSON Schema的校验,才算通过校验。例如,如果patternProperties对应的值如下:

{
    "patternProperties": {
        "^S_": {
            "type": "number"
        },
        "^I": {
            "type": "string"
        }
    }
}

在待校验JSON对象中,所有以S开头的key的value都必须是number,所有以I开头的一级key的value都必须是string。

additionnalProperties

如果待校验JSON对象中存在,既没有在properties中被定义,又没有在patternProperties中被定义,那么这些一级key必须通过additionalProperties的校验。

对于array类型的关键字

items、additionalItems、minItems、maxItems、uniqueItems、contains

items

当该关键字的值是一组有效的JSON Schema时,只有待校验JSON数组的所有元素通过items的值中对应位置上的JSON Schema的校验,那么,整个待校验JSON数组才算通过校验。

{
    "type": "array",
    "items": {
        "type": "string",
        "maxLength": 5
    }
}

如果items定义的有效的JSON Schema的数量和待校验JSON数组中元素的数量不一致,那么就要采用“取小原则”。即,如果items定义了3个JSON Schema,但是待校验JSON数组只有2个元素,这时,只要待校验JSON数组的前两个元素能够分别通过items中的前两个JSON Schema的校验,那么,我们认为待校验JSON数组通过了校验。而,如果待校验JSON数组有4个元素,这时,只要待校验JSON数组的前三个元素能够通过items中对应的JSON Schema的校验,我们就认为待校验JSON数组通过了校验。

例如,如果items的值如下:

{
    "type": "array",
    "items": [
        {
            "type": "string",
            "minLength": 5
        },
        {
            "type": "number",
            "minimum": 10
        },
        {
            "type": "string"
        }
    ]
}

上面的JSON Schema指出了待校验JSON数组应该满足的条件,数组的第一个元素是string类型,且最小可接受长度为5,数组的第二个元素是number类型,最小可接受的值为10,数组的第三个元素是string类型。那么下面这两个JSON数组明显是符合要求的,具体内容如下:

["green", 10, "good"]

["helloworld", 11]

additionalItems

需要注意的是,该关键字只有在items关键字的值为一组有效的JSON Schema的时候,才会进行校验,用于规定超出items中JSON Schema总数量之外的待校验JSON数组中的剩余的元素应该满足的校验逻辑。当然了,只有这些剩余的所有元素都满足additionalItems的要求时,待校验JSON数组才算通过校验。

其实,你可以这么理解,当items的值为一组有效的JOSN Schema的时候,一般可以和additionalItems关键字组合使用,items用于规定对应位置上应该满足的校验逻辑,而additionalItems用于规定超出items校验范围的所有剩余元素应该满足的条件。如果二者同时存在,那么只有待校验JSON数组同时通过二者的校验,才算真正地通过校验。

一般的JSON数据会出现某些场景下的字段个数并不是完全的匹配,所以这种场景也很常见。

如果一个additionalItems的值如下:

{
    "type": "array",
    "items": [
        {
            "type": "string",
            "minLength": 5
        },
        {
            "type": "number",
            "minimum": 10
        }
    ],
    "additionalItems": {
        "type": "string",
        "minLength": 2
    }
}

上面的JSON Schema的意思是,待校验JSON数组第一个元素是string类型,且可接受的最短长度为5个字符,第二个元素是number类型,且可接受的最小值为10,剩余的其他元素是string类型,且可接受的最短长度为2。那么,下面三个JSON数组是能够通过校验的,具体内容如下:

["green", 10, "good"]

minItems、maxItems

在校验JSON数组中元素的个数限制,minItems指定了待校验JSON数组可以接受的最少元素个数,而maxItems指定了待校验JSON数组可以接受的最多元素个数。

uniqueItems

这个关键字是一个boolean类型的值,关键字的值为true时,只有待校验JSON数组中的所有元素都具有唯一性时,才能通过校验。当该关键字的值为false时,任何待校验JSON数组都能通过校验。

contains

在要校验JSON数组中至少有一个元素能够通过该关键字指定的JSON Schema的校验,整个数组才算通过校验。

对于integer或number类型的关键字

multipleOf、maximum、exclusiveMaximum、minimum、exclusiveMinimum

multipleOf

该关键字的值是一个大于0的number,即可以是大于0的int,也可以是大于0的float。

只有待校验的值能够被该关键字的值整除,才算通过校验。

如果含有该关键字的JSON Schema如下:

{
    "type": "integer",
    "multipleOf": 2
}

那么,2、4、6都是可以通过校验的,但是,3、5、7都是无法通过校验的,当然了,2.0、4.0也是无法通过校验的。

如果含有multipleOf关键字的JSON Schema如下:

{
    "type": "number",
    "multipleOf": 2
}

那么,2、2.0、4、4.0都是可以通过校验的,但是,3、3.0都是无法通过校验的。

maximum

该关键字的值是一个number,即可以是int,也可以是float。

该关键字规定了待校验元素可以通过校验的最大值。

exclusiveMaximum

该关键字通常和maximum一起使用,当该关键字的值为true时,表示待校验元素必须小于maximum指定的值;当该关键字的值为false时,表示待校验元素可以小于或者等于maximum指定的值。

minimum、exclusiveMinimum

minimum、exclusiveMinimum关键字的用法和含义与maximum、exclusiveMaximum相似。唯一的区别在于,一个约束了待校验元素的最小值,一个约束了待校验元素的最大值。

对于string类型的关键字

maxLength、minLength、pattern、format

maxLength

该关键字规定了待校验JSON元素可以通过校验的最大长度,待校验JSON元素的最大长度必须小于或者等于该关键字的值。

minLength

该关键字规定了待校验JSON元素可以通过校验的最小长度,即待校验JSON元素的最小长度必须大于或者等于该关键字的值。

pattern

只有待校验JSON元素符合该关键字指定的正则表达式,才算通过校验。

format

该关键字的值只能是以下取值:

  • date-time(时间格式)
  • email(邮件格式)
  • hostname(网站地址格式)
  • ipv4
  • ipv6
  • uri
  • uri-reference
  • uri-template
  • json-pointer。

如果待校验的JSON元素正好是一个邮箱地址,那么,我们就可以使用format关键字进行校验,而不必通过pattern关键字指定复杂的正则表达式进行校验。例如:

{
    "type": "string",
    "format": "email"
}

所有类型都可用的关键字

enum、const、allOf、anyOf、oneOf、not、default

enum

该关键字的值是一个数组,该数组至少要有一个元素,且数组内的每一个元素都是唯一的。

如果待校验的JSON元素和数组中的某一个元素相同,则通过校验。否则,无法通过校验。

注意,该数组中的元素值可以是任何值,包括null。

const

如果待校验的JSON元素的值和该关键字指定的值相同,则通过校验。否则,无法通过校验。

allOf

该关键字的值是一个非空数组,只有待校验JSON元素通过数组中所有的JSON Schema校验,才算真正通过校验。

anyOf

该关键字的值是一个非空数组,如果待校验JSON元素能够通过数组中的任何一个JSON Schema校验,就算通过校验。

oneOf

该关键字的值是一个非空数组,如果待校验JSON元素能且只能通过数组中的某一个JSON Schema校验,才算真正通过校验。不能通过任何一个校验和能通过两个及以上的校验,都不算真正通过校验。

not

只有待校验JSON元素不能通过该关键字指定的JSON Schema校验的时候,待校验元素才算通过校验。

default

该关键字常常用来指定待校验JSON元素的默认值,当然,这个默认值最好是符合要求的,即能够通过相应的JSON Schema的校验。