chenxiaochun / blog

🖋️ChenXiaoChun's blog
181 stars 15 forks source link

JSON-Schema(上篇) #43

Open chenxiaochun opened 6 years ago

chenxiaochun commented 6 years ago

JSON Schema 是一个用来验证 JSON 数据结构的强大工具,它具体可以用来:

假设我们要构建一个表示商品目录的数据结构,它包含idnameprice和一个可选的tags

{
    "id": 1,
    "name": "A green door",
    "price": 12.50,
    "tags": ["home", "green"]
}

作为开发者看到这个数据结构,可能通常都会产生一些疑问,比如:

因此,当你在讨论这些数据格式问题时,你就很希望能有一份文档来描述这些字段的意义和它们支持的有效值是什么。所以,JSON Schema 就是用来帮助 JSON 数据来回答这些问题的一份标准规范。

我们先来看一个最基础的 JSON Schema:

{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object"
}

上面的 schema 拥有四个属性关键字。

下面我们来看如何通过 schema 来一个个的回答上面提出的问题。

第一个问题,id是什么?

id是一个商品典型地、不可重复的数字类型标识,对于商品来说至关重要,因此它绝对是必需的一个数据字段。因此,我们更新上面的 schema,添加一个required字段,并且添加字段值id

{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object",
    "properties": {
        "id": {
            "description": "The unique identifier for a product",
            "type": "integer"
        }
    },
    "required": ["id"]
}

接下来第二个问题,name字段是必须的吗?

name是一个用来描述商品的字符串类型字段,商品肯定是有名称的,因此它也是一个必需的字段。接着更新 schema,在required中添加name字段值。

{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object",
    "properties": {
        "id": {
            "description": "The unique identifier for a product",
            "type": "integer"
        },
        "name": {
            "description": "Name of the product",
            "type": "string"
        }
    },
    "required": ["id", "name"]
}

第三个问题,price可以为 0 吗?

一般来说没有免费的商品,price也是必需的。所以,我们使用exclusiveMinimum字段来指定它的有效值。可是,如果你想把 0 也作为有效值,那就换成minimum来代替它就好。更新 schema,添加exclusiveMinimum字段值,并且在required中添加price

{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "title": "Product",
    "description": "A product from Acme's 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",
            "exclusiveMinimum": 0
        }
    },
    "required": ["id", "name", "price"]
}

最后一个问题,所有的tags值必须是字符类型吗?

与其它的字段不同,tags作为一个数组可以拥有很多的字段值。假设我们这里规定tags的字段值必须为字符串类型,字段值不能重复且必须至少有一个值。那使用 schema 应该这样来描述:

{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "title": "Product",
    "description": "A product from Acme's 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",
            "exclusiveMinimum": 0
        },
        "tags": {
            "type": "array",
            "items": {
                "type": "string"
            },
            "minItems": 1,
            "uniqueItems": true
        }
    },
    "required": ["id", "name", "price"]
}

上面的示例仅仅展示了 JSON schema 的部分定义规则。接下来的示例是一个商品数组列表,并且添加了两个新字段。dimensions表示商品的尺寸,warehouseLocation表示商品的仓库地址。

[
    {
        "id": 2,
        "name": "An ice sculpture",
        "price": 12.50,
        "tags": ["cold", "ice"],
        "dimensions": {
            "length": 7.0,
            "width": 12.0,
            "height": 9.5
        },
        "warehouseLocation": {
            "latitude": -78.75,
            "longitude": 20.4
        }
    },
    {
        "id": 3,
        "name": "A blue mouse",
        "price": 25.50,
        "dimensions": {
            "length": 3.1,
            "width": 1.0,
            "height": 1.0
        },
        "warehouseLocation": {
            "latitude": 54.4,
            "longitude": -32.7
        }
    }
]

使用 schema 描述为:

{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "title": "Product set",
    "type": "array",
    "items": {
        "title": "Product",
        "type": "object",
        "properties": {
            "id": {
                "description": "The unique identifier for a product",
                "type": "number"
            },
            "name": {
                "type": "string"
            },
            "price": {
                "type": "number",
                "exclusiveMinimum": 0
            },
            "tags": {
                "type": "array",
                "items": {
                    "type": "string"
                },
                "minItems": 1,
                "uniqueItems": true
            },
            "dimensions": {
                "type": "object",
                "properties": {
                    "length": {"type": "number"},
                    "width": {"type": "number"},
                    "height": {"type": "number"}
                },
                "required": ["length", "width", "height"]
            },
            "warehouseLocation": {
                "description": "Coordinates of the warehouse with the product",
                "$ref": "http://json-schema.org/geo"
            }
        },
        "required": ["id", "name", "price"]
    }
}

你应该已经注意到,warehouseLocation中的$ref指向了一个在线的 schema 规则,以替代直接在当前schema 中编写规则的方式,这样也是可以的。这种方式带来的好处就是 schema 规则的最大化重复利用,尽可能做到:一次编写,随处引用。

源文链接:http://json-schema.org/example1.html