标准规范 (Standards)
你当前正在浏览历史版本 Vert.x 4.0.3 的文档。 访问本页面的 最新版本。

Vert.x JSON Schema 校验引擎 (vertx-json-schema)

Preview

Vert.x JSON Schema 为 JSON Schema 规范提供了可扩展的响应式异步实现。 你可以使用 JSON Schema 校验任意 JSON 数据结构。本模块主要特性包括:

  • 支持 Draft 2020-12 规范

  • 支持 Draft 2019-09 规范

  • 支持 Draft 7 规范

  • 支持 Draft 4 规范

  • $ref 跨 Schema 外部引用解析(Dereferencing)与缓存加速

  • 用于通过纯 Java 代码流式构建 Schema 的类型安全 DSL

引入依赖

要在项目中使用 Vert.x JSON Schema,请在构建描述文件中添加以下依赖:

  • Maven(在 pom.xml 中):

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-json-schema</artifactId>
  <version>5.0.12</version>
</dependency>
  • Gradle(在 build.gradle 文件中):

dependencies {
  compile 'io.vertx:vertx-json-schema:5.0.12'
}

核心概念

1. JsonSchema

Schema 声明可以呈现为两种形态:

  • 标准 JSON 对象形态

  • 布尔值形态(如 true / false)

JsonSchema 接口对这两种形态提供了统一封装抽象,使上层调用无须反复分支判断底层形态。

2. SchemaRepository

SchemaRepository 负责管理并维护 JsonSchema 实例集合。它预先对 Schema 进行引用解引(Dereference)以大幅提升后续校验性能。该仓库本质是一个键值存储,不允许存在重复的 Schema ID。

仓库可随后创建感知仓库内全部子 Schema 的 Validator 校验器实例。

3. Validator

Validator 校验器基于给定的根 Schema 对输入 JSON 对象执行结构校验。输出报告的详细度可通过配置自由定制。

解析与加载 Schema

在涉及多个复杂 Schema 或嵌套子 Schema 时,推荐统一使用 Repository:

解析 Schema 首先需要实例化 JsonSchema 并完成基础配置。由于 Schema 内部可能包含 $ref 相对引用,校验器与仓库需要明确应用的 baseUri,以便在子 Schema 间解析跨文件引用。仅进行引用解引时无须预先绑定草案版本:

SchemaRepository repository =
  SchemaRepository.create(new JsonSchemaOptions().setBaseUri("https://vertx.io"));

你可以复用 JsonSchema 实例构建不同的 Validator,也可以通过 JsonParser 流式解析 Schema:

JsonSchema schema = JsonSchema.of(object);

// 或者通过仓库执行引用解引并注册:
repository.dereference(JsonSchema.of(object));

出于运行时安全性考虑,本模块绝不会在校验阶段尝试通过网络自动下载外部 $ref 引用的子 Schema。所有必需的外部子 Schema 必须预先显式注册至 Repository 对象中!

执行数据校验

鉴于 JSON Schema 语法的动态特性以及 if-then-else 等高级条件判定,在流式场景下无法完全实现单遍非阻塞校验。因此校验在底层是一个同步阻塞计算操作。若预料校验过程计算密集且耗时较长,建议在专属 Worker 线程池中执行或使用 executeBlocking 封装。

要校验 Schema:

OutputUnit result = Validator.create(
    schema,
    new JsonSchemaOptions().setDraft(Draft.DRAFT7))
  .validate(json);

if (result.getValid()) {
  // 校验成功!数据符合规范
} else {
  System.out.println("校验失败,错误原因: " + result.getError() + ",错误类型: " + result.getErrorType());
}

若校验失败,你可以通过 OutputErrorType 排查深层诱因。

通过 Java 代码与 DSL 动态构建 Schema

若希望直接用 Java 代码动态声明 Schema,可以使用内置的 DSL。该功能当前支持 Draft-7 规范。

首先静态导入 Schemas 与 Keywords:

创建基础类型 Schema

在 Schemas 中提供了各类基础类型的静态构建器:

SchemaBuilder intSchemaBuilder = intSchema();
SchemaBuilder objectSchemaBuilder = objectSchema();

追加关键字约束

你可以通过 Keywords 提供的静态方法为不同类型的 Schema 附加约束条件:

stringSchema()
  .with(format(StringFormat.DATETIME));
arraySchema()
  .with(maxItems(10));
schema() // 同时接受数组或整型的通用 Schema
  .with(type(SchemaType.ARRAY, SchemaType.INTEGER));

组织复合数据结构

创建带有特定属性与附加属性约束的对象 Schema:

objectSchema()
  .requiredProperty("name", stringSchema())
  .requiredProperty("age", intSchema())
  .additionalProperties(stringSchema());

创建数组元素 Schema:

arraySchema()
  .items(stringSchema());

创建元组(Tuple)位置约束 Schema:

tupleSchema()
  .item(stringSchema())   // 第 1 个元素必须为字符串
  .item(intSchema())      // 第 2 个元素必须为整型
  .item(booleanSchema()); // 第 3 个元素必须为布尔值

$ref 引用与别名 (Aliases)

通过 Schemas.ref 引入 $ref 引用;使用 id 方法为当前 Schema 赋予 $id 标识。

你还可以为 DSL 构建的 Schema 定义别名(Alias),并借助 Schemas.refToAlias 在其它位置轻松复用:

intSchema()
  .alias("myInt");

objectSchema()
  .requiredProperty("anInteger", refToAlias("myInt"));

导出 JSON 结构

定义完成后,调用 toJson 即可将其转换为规范的 JSON Schema 对象:

JsonObject schema = objectSchema()
  .requiredProperty("name", stringSchema())
  .requiredProperty("age", intSchema())
  .additionalProperties(stringSchema())
  .toJson();