Contents

JSON模式简介

1. 概述

JSON Schema是一种声明性语言,用于验证JSON Object的格式和结构。它允许我们指定特殊原语的数量来准确描述有效JSON 对象的外观。

JSON Schema规范分为三个部分:

  • JSON Schema Core :JSON Schema Core 规范是定义模式术语的地方。
  • JSON Schema Validation :JSON Schema Validation 规范是定义定义验证约束的有效方法的文档。本文档还定义了一组关键字,可用于指定 JSON API 的验证。在接下来的示例中,我们将使用其中一些关键字。
  • JSON Hyper-Schema :这是 JSON Schema 规范的另一个扩展,其中定义了超链接和超媒体相关的关键字。

2. 定义 JSON 模式

现在我们已经定义了JSON Schema的用途,让我们创建一个JSON Object和描述它的相应JSON Schema

以下是表示产品目录的简单JSON Object

{
    "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关键字表明此模式是根据 v4 规范草案编写的。
  • 标题和描述关键字只是描述性的,因为它们不会对正在验证的数据添加约束***。***模式的意图是用这两个关键字来说明的:描述一个产品。
  • type关键字定义了我们JSON数据的第一个约束:它必须是JSON Object。 此外,JSON 模式可能包含不是模式关键字的属性。在我们的例子中idnameprice 将是JSON Object的成员(或属性) 。 对于每个属性,我们可以定义类型。我们将idname定义为string 并将price定义为number。在JSON Schema中,数字可以有最小值。默认情况下,这个最小值是包含的,所以我们需要指定ExclusiveMinimum

最后,Schema告诉idnameprice必需的。

3. 使用 JSON Schema 进行验证

随着我们的JSON Schema到位,我们可以验证我们的JSON Object

有许多 可以完成这项任务。对于我们的示例,我们选择了 Java json-schema 库。

首先,我们需要在pom.xml中添加以下依赖项:

<dependency>
    <groupId>org.everit.json</groupId>
    <artifactId>org.everit.json.schema</artifactId>
    <version>1.3.0</version>
</dependency>

最后,我们可以编写几个简单的测试用例来验证我们的JSON Object

@Test
public void givenInvalidInput_whenValidating_thenInvalid() throws ValidationException {
    JSONObject jsonSchema = new JSONObject(
      new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/schema.json")));
    JSONObject jsonSubject = new JSONObject(
      new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/product_invalid.json")));
    
    Schema schema = SchemaLoader.load(jsonSchema);
    schema.validate(jsonSubject);
}

在这种情况下,抛出的ValidationException将指向*#/price*。如果您查看控制台,它将打印以下输出:

#/price: 0.0 is not higher than 0

第二个测试如下所示:

@Test
public void givenValidInput_whenValidating_thenValid() throws ValidationException {
    JSONObject jsonSchema = new JSONObject(
      new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/schema.json")));
    JSONObject jsonSubject = new JSONObject(
      new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/product_valid.json")));
    Schema schema = SchemaLoader.load(jsonSchema);
    schema.validate(jsonSubject);
}

由于我们使用了有效的JSON Object,因此不会引发验证错误。