网站首页 > 技术文章 正文
什么是 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 的知识可参考:
- http://json-schema.org/
- github:java-json-tools/json-schema-validator
猜你喜欢
- 2025-01-09 精通Spring Boot 3 : 13. Spring Cloud 与 Spring Boot (4)
- 2025-01-09 Spring Boot集成Redis Search快速入门Demo
- 2025-01-09 Spring Boot 3.x嵌入MongoDB 进行测试
- 2025-01-09 java安全之fastjson链分析
- 2025-01-09 MyBatis初级实战之五:一对一关联查询
- 2025-01-09 精通Spring Boot 3 : 8. Spring Boot 测试 (2)
- 2025-01-09 DevSecOps 管道: 使用Jenkins实现安全的多语言应用程序
- 2025-01-09 Liquibase+Spring+Maven: 管理数据库轻松搞定
- 2025-01-09 比较一下JSON与XML两种数据格式?
- 2025-01-09 Java批量导入时,如何去除重复数据并返回结果?
- 05-15总结雅虎前端性能优化技巧(16条)
- 05-15日常生活中吃雪莲果有养生功效也有危害
- 05-15API 安全之认证鉴权
- 05-15Chaosblade: 阿里一个超级牛逼的混沌实验实施工具
- 05-15膨来仙岛丨搞电竞的都是什么成分?
- 05-15大事全知晓!2022年新闻日历来了!
- 05-15你是有多久没看过麦田圈了?一篇文章全面回顾2015麦田圈季
- 05-15魔兽世界9.1 刻希亚寻找宝箱、稀有WA(转自nga)
- 最近发表
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- sqlset (64)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- js数组插入 (83)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)