JSON Schema 简述

354 阅读1分钟

一、什么是 JSON Schema?

JSON Schema 是一种用 JSON 编写的声明式语言,用来描述和验证 JSON 数据的结构、数据类型、格式、取值范围、必填字段等规则。它相当于 JSON 的“接口文档”,确保数据符合预期格式,常用于 API 设计、数据交换、配置管理等场景。

下面以一个简单的 user_schema.json 为例:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "id": { "type": "integer" },
    "email": { "type": "string", "format": "email" },
    "tags": {
      "type": "array",
      "items": { "type": "string" },
      "minItems": 1
    }
  },
  "required": ["id", "email"]
}

有效数据:

{ "id": 123, "email": "user@example.com", "tags": ["admin"] }

无效数据:id 为字符串,缺少 email

{ "id": "abc", "tags": ["guest"] }

二、更多配置项

除了上文 user_schema.json 中的基础配置项,还有更多可选的额外配置项,以下是一些补充:

  1. $schema:关键字必须以 $ 开头,告诉校验器“本 Schema 按哪个版本的标准来写”,非必需;
  2. 数据类型:支持基础类型,以及组合类型(如 [string, null] 表示可为字符串或 null);
  3. additionalProperties:控制是否允许额外字段;
  4. 字符串格式:如 "format": "email" 验证邮箱,"pattern": "^[A-Z]+$" 用正则匹配;
  5. 数值范围:minimum, maximum, exclusiveMinimum 等;
  6. 枚举值:"enum": ["red", "green", "blue"] 限制只能取特定值;
  7. $ref:对公共定义片段的复用;
  8. 组合:allOf(全部满足)、anyOf(任一满足)、oneOf(仅满足一个);
  9. 以及更多高级特性,此处不作深入。

三、在 Java 中使用 JSON Schema 进行校验

1、引入和获取

推荐使用 networknt/json-schema-validator 作为校验器,性能最高。我在这里使用的是 java-json-tools/json-schema-validator,API 稍有不同。

// 引入依赖
implementation("com.github.java-json-tools:json-schema-validator:2.2.14")

然后获取编写好的 Schema,无论是直接读取存储的 json 文件,还是由入参的 json 字符串转换而来,都要自行获取,内容以这里的 schema.json 为例:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["name","age"],
  "properties": {
    "name": { "type": "string" },
    "age":  { "type": "integer", "minimum": 18 }
  }
}

2、校验

具体的校验代码示例如下:

// 1. 获取入参中的 schema
ObjectMapper mapper = new ObjectMapper();
JsonNode schemaNode = mapper.valueToTree(inputDTO.get("schema"));

// 2. 创建校验器
JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
JsonSchema jsonSchema = factory.getJsonSchema(schemaNode);

// 3. 待校验数据
JsonNode data = mapper.readTree("{\"name\":\"Tom\",\"age\":17}");

// 4. 执行校验
ProcessingReport report = jsonSchema.validate(data);

// 5. 处理结果
if (!report.isSuccess()) {
    throw new BusinessException(BusinessCodeEnum.CSJYSB, "未通过必填参数校验");
}