Json -schema
- 1.对象的效验
- 2.数组套对象的效验
- 3. 字符串的效验
- 长度效验(minLength)(maxLength)
- 正则效验
- 日期和时间
- 4.对象套对象效验
- 5.对象套数组
- 6. 其他参数
- required(必须要填)
- enum(范围之内)
- not(不)
- anyOf 和allOf(双方为真,有一个为真)
- format
- 7. $ref 的使用(定义全局枚举)
- 参考文档
https://json-schema.org/understanding-json-schema/index.html
JSON Schema是什么?
根据JSON Schema 规范的定义,JSON模式是一种JSON媒体类型,用于定义JSON数据的结构。JSON模式旨在定义JSON数据的验证、文档、超链接导航和交互控制
- 首先是添加pom
<!-- json格式效验测试-->
<dependency>
<groupId>com.github.everit-org.json-schema</groupId>
<artifactId>org.everit.json.schema</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
- 先从最简单的对象的校验开始先了解其他语法在进一步逐一渗透
1.对象的效验
- 接口测试
- 这里说一下粗略的流程
1. 首先需要有一个需要进行效验的实体类
2. 通过JSON.toJSONString将其转为实体类
3. getClass().getResourceAsStream是获取到json的配置文件
4. 将其变为new org.json.JSONObjec对象类型的数据,
5. 将我们 上面转为json的实体类变为 new JSONObjec
6. 通过schema.validate()去进行文件的效验,如果正确返回true,否则直接抛异常
7. 后面就是将异常翻译一下传给前端,让用户知道是哪个格式出错了
import com.alibaba.fastjson.JSON;
import com.bj.cy.Service.bradnApiService;
import com.bj.cy.enity.brand;
import com.bj.cy.utils.CheckAnalysisList;
import com.bj.cy.utils.CheckRowVo;
import com.bj.cy.utils.nety.test1;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.everit.json.schema.ValidationException;
import org.everit.json.schema.loader.SchemaLoader;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@ApiOperation("检测数据效验")
@RequestMapping(value = "test2", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public Object test2(@RequestBody test1 test1) {
//这个是你打算验证的JSON
String userBehavioAudits = JSON.toJSONString(test1);
//这个就是你设定的标准JSON
InputStream inputStream = getClass().getResourceAsStream("/test.json");
org.json.JSONObject Schema = new org.json.JSONObject(new JSONTokener(inputStream));
org.everit.json.schema.Schema schema = SchemaLoader.load(Schema);
try {
JSONObject myJsonObject = new JSONObject(userBehavioAudits);
schema.validate(myJsonObject);
} catch (ValidationException e) {
String errorMessage = e.getAllMessages().toString().replace("not found", "为空值!");
String errorMessage1 = errorMessage.replace("is not a valid enum value", "不在枚举范围内!");
String errorMessage2 = errorMessage1.replace("expected maxLength:", "字段最大长度为:");
String errorMessage3 = errorMessage2.replace("actual:", "当前实际长度:");
String errorMessage4 = errorMessage3.replace("is not less or equal to ", "最大范围为为:");
String errorMessage5 = errorMessage4.replace("subject must not be valid against schema", "不可是以下枚举值");
return errorMessage5;
}
return "str";
}
- 实体类(test)
@Data
public class test1 {
private String name;
private String sex;
private String filename;
}
- json效验文件
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/example.json",
"type": "object",
"additionalProperties": true,
"required": [
"name",
"sex",
"filename"
],
"properties": {
"name": {
"$id": "#/properties/name",
"type": "string",
"maxLength": 36,
"minLength": 10,
"not": {
"enum": [
"String",
"string"
]
}
},
"sex": {
"$id": "#/properties/sex",
"type": "string",
"not": {
"enum": [
"String",
"string"
]
}
},
"filename": {
"$id": "#/properties/filename",
"type": "string",
"not": {
"enum": [
"String",
"string"
]
}
}
}
}
2.数组套对象的效验
- 数组套对象其实和上面的,没什么区别,for循环然后把错误信息add一下返回
@ApiOperation("检测数据效验")
@RequestMapping(value = "test3", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public Object test3(@RequestBody List<test1> test1) {
List<String>errLis=new ArrayList<>();
//这个是你打算验证的JSON
String userBehavioAudits = JSON.toJSONString(test1);
//因为是数组所以要转为Jsonarrat类型的
JSONArray array = new JSONArray(userBehavioAudits);
//这个就是你设定的标准JSON
InputStream inputStream = getClass().getResourceAsStream("/test.json");
org.json.JSONObject Schema = new org.json.JSONObject(new JSONTokener(inputStream));
org.everit.json.schema.Schema schema = SchemaLoader.load(Schema);
for (int i = 0; i < test1.size(); i++) {
try {
JSONObject jsonObject = array.getJSONObject(i);
// JSONObject myJsonObject = new JSONObject(userBehavioAudits);
schema.validate(jsonObject);
} catch (ValidationException e) {
String errorMessage = e.getAllMessages().toString().replace("not found", "为空值!");
String errorMessage1 = errorMessage.replace("is not a valid enum value", "不在枚举范围内!");
String errorMessage2 = errorMessage1.replace("expected maxLength:", "字段最大长度为:");
String errorMessage3 = errorMessage2.replace("actual:", "当前实际长度:");
String errorMessage4 = errorMessage3.replace("is not less or equal to ", "最大范围为为:");
String errorMessage5 = errorMessage4.replace("subject must not be valid against schema", "不可是以下枚举值");
errLis.add(errorMessage5);
}
}
return errLis;
}
3. 字符串的效验
长度效验(minLength)(maxLength)
- 效验最大长度是36,最小长度是10,在这个范围之内为true反之为false
正则效验
- 效验其是否是一个邮箱
日期和时间
- “date-time”:日期和时间在一起,例如。2018-11-13T20:20:39+00:00
“time”:草案 7 时间中的新内容,例如,20:20:39+00:00
“date”:草案 7 日期中的新增内容,例如,.2018-11-13
“duration”:2019-09 年草案中的新增内容 ISO 定义的持续时间 8601 ABNF 表示“持续时间”。为 例如,表示持续时间为 3 天
4.对象套对象效验
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/example.json",
"type": "object",
"additionalProperties": true,
"required": [
"shoop",
"wor"
],
"properties": {
"shoop": {
"$id": "#/properties/name",
"type": "string",
"maxLength": 5
},
"wor": {
"$id": "#/properties/sex",
"type": "string",
"maxLength": 5
},
"test": {
"type": "object", //这个是主要的因为对象的类型是object类型
"properties": {
"name": {
"type": "string",
"maxLength": 5
}
}
}
}
}
@Data
public class test2 {
private String shoop;
private String wor;
private test1 test;
}
@Data
public class test1 {
private String name;
private String sex;
private String filename;
}
5.对象套数组
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/example.json",
"type": "object",
"additionalProperties": true,
"required": [
"shoop",
"wor"
],
"properties": {
"shoop": {
"$id": "#/properties/name",
"type": "string",
"maxLength": 5
},
"wor": {
"$id": "#/properties/sex",
"type": "string",
"maxLength": 5
},
"test": {
"type": "array", //表名其是个数组
"items": { //表示每一个元素
"properties": {
"name": {
"type": "string",
"maxLength": 5
}
}
}
}
}
}
@Data
public class test3 {
private String shoop;
private String wor;
private List<test1> test;
}
@Data
public class test1 {
private String name;
private String sex;
private String filename;
}
6. 其他参数
required(必须要填)
enum(范围之内)
not(不)
- 增加了not的枚举是只有等于里面的数才会出错
anyOf 和allOf(双方为真,有一个为真)
- anyOf 是有一个为真就可以
- 反之则放行
format
- format关键字允许对常用的某些类型的字符串值进行基本语义验证:
/**
format 的可能取值:
"date-time":日期和时间在一起,例如, 2018-11-13T20:20:39+00:00。
"time":draft7的时间,例如,20:20:39+00:00
"date":draft7的日期,例如,2018-11-13。
"hostname": Internet 主机名
"idn-hostname":国际化 Internet 主机名
"ipv4":IPv4 地址
"ipv6":IPv6 地址
"uri":通用资源标识符 (URI) 。
"uri-reference":一个 URI 引用(URI 或相对引用)
"iri":“uri”的国际化等价物。
"iri-reference":“uri-reference”的国际化等价物
"uri-template":一个 URI 模板(任何级别)
"json-pointer":一个 JSON 指针
"relative-json-pointer":一个相对 JSON 指针。
"regex":正则表达式。
*/
{
"type": "string",
"format": "date-time"
7. $ref 的使用(定义全局枚举)
-
首先,在 $defs 中定义了一个名为 “myEnumValues” 的结构,其中包含了所有可能的枚举值。然后,在 properties 中,我们使用 $ref 关键字引用了 “myEnumValues” 结构,同时将其应用于所有需要相同枚举值的参数。
通过这种方式,你只需要在 myEnumValues 结构中定义所有的枚举值,就可以在需要的地方轻松重复使用,并且能够具备更好的可读性和维护性。
-
看我如下代码,明显的是代码拢余了,每个都要写一样的东西,我们就可以使用,自定义结构
"$defs": {
"myEnumValues": {
"type": "string",
"not":{
"enum": ["string"]
}
}
},