什么是JSON Schema
JSON Schema,也称为JSON模式,下面一段话来自百度百科的介绍:
JSON Schema是描述你的JSON数据格式;JSON模式(应用程序/模式+ JSON)有多种用途,其中之一就是实例验证。验证过程可以是交互式或非交互式的。例如,应用程序可以使用JSON模式来构建用户界面使互动的内容生成除了用户输入检查或验证各种来源获取的数据。
一般使用JSON Schema来进行JSON数据格式验证,在数据提交到业务层次之前进行JSON格式的验证。
jsonschema百度百科
JSON Schema官网的描述摘要:http://json-schema.org/
- JSON Schema是基于JSON格式定义JSON数据结构的规范
- 用于描述现有的数据格式(JSON数据)
- 清晰的人机可读文档:定义的JSON Schema具有人类和机器都可读的特性
- 使用JSON Schema可完成完整的JSON结构和数据验证
- 可用于自动化测试和确保客户提交的数据质量(如下我们只讨论在自动化测试中的应用)
下面是一段JSON示例:
文档中包含如下信息:
- 一个老师的唯一标识符:teacherId
- 一个老师的名称:teacherName
- 老师的年龄:age
- 老师的标签:tags
{
"teacherId": 1,
"teacherName": "Happy",
"age": 18,
"tags": [ "JAVA", "Python","Automation" ]
}
例子很简单,但是中间有些问题有待解决,这也是我们在自动化测试中可能会关注的信息,比如以下这些:
- teacherId是啥?
- teacherName是必需的吗?
- 年龄字段age可以为0吗?
- 所有的标签都是字符串类型的值吗?
如果在自动化测试中需要来验证上述问题,方法一可以通过提取数据的方式完成,参考之前我写过的文章:
使用 JsonPath 完成接口自动化测试中参数关联和数据验证
使用JsonPath更适合关键信息的提取和验证,JSON Schema更适合回答上面的这些问题。
开始写JSON Schema
首先我们从如下一些关键字开始:
- $schema:该关键字声明该模式是根据标准的特定草案编写的,主要用于版本控制,可省略
- $id:该关键字定义模式的URI,可省略
- title和description:该JSON Schema的注释和描述信息,不会向验证的数据调节约束
- type:该关键字会定义JSON数据的第一个约束,比如是JSON对象还是数组
针对上述JSON 案例初步编写的JSON Schema如下
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/teacher.schema.json",
"title": "老师信息",
"description": "柠檬班的一个老师信息",
"type": "object"
}
定义属性
teacherId 属性
- teacherId是老师的唯一标识符,是不可缺少的
- teacherId类型是整型
根据约束我们在上面JSON Schema更新如下:
- 添加一个属性验证的关键字(key):properties
- 添加一个teacherId的key,描述和约束如下:
- description:描述这个属性
- type:属性类型
- 添加一个required关键字(key),在列表中加入teacherId,表示teacherId是必需的
最后的JSON Schema如下:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/teacher.schema.json",
"title": "老师信息",
"description": "柠檬班的一个老师信息",
"type": "object",
"properties": {
"teacherId": {
"description": "老师信息的唯一标识符",
"type": "integer"
}
},
"required": [ "teacherId" ]
}
teacherName 属性
- teacherName是老师的名称
- 老师的名称也是一个老师必需的信息
- 老师的名称是字符串类型
添加对teacherName属性的约束后,JSON Schema如下,其中:
- 往properties中加入了teacherName的描述和约束信息
- 往required列表中加入teacherName字段
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/teacher.schema.json",
"title": "老师信息",
"description": "柠檬班的一个老师信息",
"type": "object",
"properties": {
"teacherId": {
"description": "老师信息的唯一标识符",
"type": "integer"
},
"teacherName": {
"description": "老师的名称",
"type": "string"
}
},
"required": [ "teacherId","teacherName" ]
}
age 属性
- age字段是数值类型,使用number约束
- 约定柠檬班老师的年龄不能不能小于18岁,否则就算雇佣童工了
- 使用exclusiveMinimum关键字表示年龄必须大于18(不包含18),使用minimum关键字指定年龄最小为18岁(包含18岁)
升级后JSON Schema如下
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/teacher.schema.json",
"title": "老师信息",
"description": "柠檬班的一个老师信息",
"type": "object",
"properties": {
"teacherId": {
"description": "老师信息的唯一标识符",
"type": "integer"
},
"teacherName": {
"description": "老师的名称",
"type": "string"
},
"age": {
"description": "老师的年龄",
"type": "number",
"minimum": 18
}
},
"required": [ "teacherId","teacherName","age" ]
}
tags属性
tags属性要求如下:
- 老师标签不是必需的
- 如果有tags,那么至少要有一个标签
- 所有的标签必需要是唯一的,一个老师的标签不能重复
- 所有的标签必须要是文本
JSON Schema需要做如下修改:
- 在properties中添加一个tags属性
- tags的类型设置为array
- 引入items的约束关键字定义数组中的元素,如下约束类型为string
- 引入minItems关键字用于约束数组中最少元素数量
- 引入uniqueItems关键字用于约束数组所有元素值是唯一的
- 因为tags可选的,所有在required中我们没有添加该属性
升级后JSON Schema如下
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/teacher.schema.json",
"title": "老师信息",
"description": "柠檬班的一个老师信息",
"type": "object",
"properties": {
"teacherId": {
"description": "老师信息的唯一标识符",
"type": "integer"
},
"teacherName": {
"description": "老师的名称",
"type": "string"
},
"age": {
"description": "老师的年龄",
"type": "number",
"minimum": 18
},
"tags": {
"description": "老师的标签",
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
},
"required": [ "teacherId","teacherName","age" ]
}
JAVA中的JSON Schema的校验
通过maven引入相关的jar包
<dependency>
<groupId>com.github.java-json-tools</groupId>
<artifactId>json-schema-validator</artifactId>
<version>2.2.10</version>
</dependency>
编写程序校验
//要校验的json字符串(如来自自动化测试中的响应结果)
String jsonStr = "{\r\n" + " \"teacherId\": 1,\r\n" + " \"teacherName\": \"Happy\",\r\n" + " \"age\": 18,\r\n"
+ " \"tags\": [ \"JAVA\", \"Python\",\"Automation\" ]\r\n" + "}";
//根据响应结果需求,编写的JSON Schema
String jsonSchema = "{\r\n" + " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\r\n"
+ " \"$id\": \"http://example.com/teacher.schema.json\",\r\n" + " \"title\": \"老师信息\",\r\n"
+ " \"description\": \"柠檬班的一个老师信息\",\r\n" + " \"type\": \"object\",\r\n" + " \"properties\": {\r\n"
+ " \"teacherId\": {\r\n" + " \"description\": \"老师信息的唯一标识符\",\r\n"
+ " \"type\": \"integer\"\r\n" + " },\r\n" + " \"teacherName\": {\r\n"
+ " \"description\": \"老师的名称\",\r\n" + " \"type\": \"string\"\r\n" + " },\r\n"
+ " \"age\": {\r\n" + " \"description\": \"老师的年龄\",\r\n" + " \"type\": \"number\",\r\n"
+ " \"minimum\": 18\r\n" + " },\r\n" + " \"tags\": {\r\n"
+ " \"description\": \"老师的标签\",\r\n" + " \"type\": \"array\",\r\n" + " \"items\": {\r\n"
+ " \"type\": \"string\"\r\n" + " },\r\n" + " \"minItems\": 1,\r\n"
+ " \"uniqueItems\": true\r\n" + " }\r\n" + " },\r\n"
+ " \"required\": [ \"teacherId\",\"teacherName\",\"age\" ]\r\n" + "}";
//创建JsonSchema工厂
JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
//通过jsonSchema获得对应JsonNode对象
JsonNode schemaNode = JsonLoader.fromString(jsonSchema);
//通过jsonStr字符串获得对应JsonNode对象
JsonNode dataNode = JsonLoader.fromString(jsonStr);
//通过jsonSchema的JsonNode对象获得JsonSchema对象
JsonSchema schema = factory.getJsonSchema(schemaNode);
//使用json-schema-validator中JsonSchema对象的validate方法对数据进行校验
//获得处理的报告信息
ProcessingReport processingReport = schema.validate(dataNode);
//获取完整报告信息
System.out.println(processingReport);
//判断校验是否成功,如果为true表示成功,否则失败
System.out.println(processingReport.isSuccess());
输出结果如下
com.github.fge.jsonschema.core.report.ListProcessingReport: success
--- BEGIN MESSAGES ---
warning: the following keywords are unknown and will be ignored: [$id]
level: "warning"
schema: {"loadingURI":"#","pointer":""}
domain: "syntax"
ignored: ["$id"]
--- END MESSAGES ---
true
最后校验的结果为true,表述校验通过,说明我们的JSON数据不管从结果还是数据上都是符合要求的,
如果我们把老师的信息调整如下:
{
"teacherId": 1,
"teacherName": "Happy",
"age": 15,
"tags": [ "JAVA", "JAVA","Automation" ]
}
校验结果为:
com.github.fge.jsonschema.core.report.ListProcessingReport: failure
--- BEGIN MESSAGES ---
warning: the following keywords are unknown and will be ignored: [$id]
level: "warning"
schema: {"loadingURI":"#","pointer":""}
domain: "syntax"
ignored: ["$id"]
error: numeric instance is lower than the required minimum (minimum: 18, found: 15)
level: "error"
schema: {"loadingURI":"#","pointer":"/properties/age"}
instance: {"pointer":"/age"}
domain: "validation"
keyword: "minimum"
minimum: 18
found: 15
error: array must not contain duplicate elements
level: "error"
schema: {"loadingURI":"#","pointer":"/properties/tags"}
instance: {"pointer":"/tags"}
domain: "validation"
keyword: "uniqueItems"
--- END MESSAGES ---
false
校验结果false,表述失败,处理报告中对校验不通过的地方也有原因描述
至此,大家可以在自己的自动化测试框架应用上JSON Schema,对响应结果为JSON格式的数据进行完整的结构和数据校验
更多关于JSON Schema的知识可参考:
欢迎来到testingpai.com!
注册 关于