1. 概述
JSON Schema 是一种用于验证JSON 对象格式和结构的声明性语言。它允许我们指定特殊的关键词数量,精确地描述一个有效的JSON 对象应该是什么样子。
JSON Schema 规范分为三部分:
- JSON Schema 核心:JSON Schema 核心规范定义了 schema 的术语。
- JSON Schema 验证:JSON Schema 验证规范定义了定义验证约束的有效方式。这份文档还定义了一组可以用于指定 JSON API 验证的关键词。在接下来的例子中,我们将使用其中的一些关键词。
- JSON 超媒体规范:这是 JSON Schema 规范的另一个扩展,其中定义了与超链接和超媒体相关的关键词。
2. 定义 JSON Schema
现在我们已经定义了 JSON Schema 的用途,让我们创建一个 JSON 对象,并为其编写相应的描述性 JSON Schema。
以下是一个简单的代表产品目录的 JSON 对象:
{
"id": 1,
"name": "Lampshade",
"price": 0
}
我们可以将其 JSON Schema 定义如下:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Product",
"description": "A product from the catalog",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a product",
"type": "integer"
},
"name": {
"description": "Name of the product",
"type": "string"
},
"price": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": true
}
},
"required": ["id", "name", "price"]
}
可以看到,JSON Schema 是一个 JSON 文档,且该文档必须是一个对象。由 JSON Schema 定义的对象成员(或属性)称为关键词。
让我们解释我们在示例中使用的关键词:
- $schema 关键词表示这个 schema 是根据draft v4 规范编写的。
- title 和 description 关键词只是描述性的,它们不会增加被验证数据的约束。通过这两个关键词表达了 schema 的意图:描述一个产品。
- type 关键词定义了对我们的 JSON 数据的第一个约束:它必须是一个 JSON 对象。
此外,JSON Schema 可能包含非 schema 关键字的属性。在我们的例子中,id、name 和 price 将是 JSON 对象的成员(或属性)。
对于每个属性,我们可以定义 type。我们定义了 id 和 name 为 string,price 为 number。在 JSON Schema 中,数字可以有最小值。默认情况下,最小值是包括在内的,因此我们需要指定 exclusiveMinimum。
最后,Schema 告诉我们 id、name 和 price 是必需的。
3. 使用 JSON Schema 进行验证
有了我们的 JSON Schema,我们可以验证我们的 JSON 对象。
有许多库可以完成这项任务。对于我们的示例,我们选择了 Java 的 json-schema 库。
首先,我们需要在 pom.xml 中添加以下依赖:
<dependency>
<groupId>com.networknt</groupId>
<artifactId>json-schema-validator</artifactId>
<version>1.0.72</version>
</dependency>
最后,我们可以编写一些简单的测试用例来验证我们的 JSON 对象:
@Test
public void givenInvalidInput_whenValidating_thenInvalid() throws IOException {
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4);
JsonSchema jsonSchema = factory.getSchema(
JSONSchemaUnitTest.class.getResourceAsStream("/schema.json"));
JsonNode jsonNode = mapper.readTree(
JSONSchemaUnitTest.class.getResourceAsStream("/product_invalid.json"));
Set<ValidationMessage> errors = jsonSchema.validate(jsonNode);
assertThat(errors).isNotEmpty().asString().contains("price: must have a minimum value of 0");
}
在这种情况下,将收到验证错误。
第二个测试看起来如下:
@Test
public void givenValidInput_whenValidating_thenValid() throws ValidationException {
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4);
JsonSchema jsonSchema = factory.getSchema(
JSONSchemaUnitTest.class.getResourceAsStream("/schema.json"));
JsonNode jsonNode = mapper.readTree(
JSONSchemaUnitTest.class.getResourceAsStream("/product_valid.json"));
Set<ValidationMessage> errors = jsonSchema.validate(jsonNode);
assertThat(errors).isEmpty();
}
由于我们使用了一个有效的 JSON 对象,所以不会抛出验证错误。
4. 总结
在这篇文章中,我们定义了什么是 JSON Schema,以及一些相关的关键字,这些关键字帮助我们定义 schema。
将 JSON Schema 与对应的 JSON 对象结合,我们可以执行一些验证任务。本文的一个简单示例可以在 GitHub 项目中找到。