JSON(JavaScript 对象表示法)是一种简单轻量级的基于文本的数据格式。JSON Schema 是一个 IETF 标准,提供了关于特定应用所需的 JSON 数据格式及其交互方式的格式。在 JSON 文档中应用此类标准可以帮助您确保类似 JSON 数据的一致性和数据有效性。
让我们看看一个包含人名及其室内和室外爱好文档的示例。
{
"id": 7,
"name": "John Doe",
"age": 22,
"hobbies": {
"indoor": [
"Chess"
],
"outdoor": [
"BasketballStand-up Comedy"
]
}
}
如果您查看上述示例,您不一定知道 id
是否可以为零(0)。您也不知道是否可以留空 age
。因此,我们需要具有关于有效数据类型和键的描述信息的元数据。此外,JSON Schema 还提供了结构化元数据的标准方式。
让我们看一下上述文档类型的 JSON Schema 示例。
{
"$schema": "https://json-schema.fullstack.org.cn/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "number"
},
"name": {
"description": "Full name of the employee",
"type": "string"
},
"age": {
"description": "Age of the employee",
"type": "number"
},
"hobbies": {
"description": "Hobbies of the employee",
"type": "object",
"properties": {
"indoor": {
"type": "array",
"items": {
"description": "List of indoor hobbies",
"type": "string"
}
},
"outdoor": {
"type": "array",
"items": {
"description": "List of outdoor hobbies",
"type": "string"
}
}
}
}
}
}
乍一看可能有些令人畏惧,但我们将逐步分析以深入了解。
在上面的示例中,我们使用了不同的关键词。以下列表解释了这些关键词的含义。
有关关键词的完整列表,请访问 json-schema.org。该链接解释了您可以在架构中使用的关键词及其目的。
如果您有一个简单的 JSON 文档,可以使用在线 JSON 架构生成器,然后根据项目需求修改架构。或者,您可以按照以下步骤从头开始构建自己的 JSON schema:
如果您已经熟悉了JSON模式的关键字和属性,我们可以直接开始创建一个基本的JSON模式。让我们从定义员工所需的五个基本关键字开始。
{
"$schema": "https://json-schema.fullstack.org.cn/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"title": "Record of Employee",
"description": "This document records the details of an employee",
"type": "object"
}
在上面的例子中,$schema
链接到标识方言和为该方言编写的有效模式的资源。
$id
关键字标识模式资源。关于这个关键字,这里有几个要点需要了解
title
关键字给出模式的一个简短描述,您可以使用description
关键字来更详细地解释模式。在上面的例子中,标题暗示这个模式是关于员工记录的,而描述详细说明了这一点。
type
关键字说明了记录的有效数据类型。在上面的例子中,type设置了此文档的约束,并告诉我们这个记录是一个对象。
上述部分中使用的模式是一个基本框架。让我们在此基础上添加一个id
字段到员工记录中。
{
"$schema": "https://json-schema.fullstack.org.cn/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "number"
}
}
}
我们添加了两个子属性,“id.description”,表示它是一个唯一标识符,以及“id.type”,解释说它是一个数字。
让我们对名称和年龄做同样的处理--但这次使用新的关键字。
{
"$schema": "https://json-schema.fullstack.org.cn/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "string"
},
"name": {
"description": "full name of the employee",
"type": "string"
"minLength":2
},
"age": {
"description": "age of the employee",
"type": "number",
"minimum": 16
}
},
"required": [
"id"
"name",
"age"
]
}
在name
属性中,我们引入了minLength
关键字,以确保属性至少有两个字符。同样,在age
属性中,我们使用了minimum
关键字,以确保员工的年龄每次都超过16岁。它可以是类型number
或类型integer
。我们还使用了required
关键字来定义必填属性。现在,让我们更进一步,并在employee
对象内部添加一个对象。
要在JSON格式中的对象内部添加对象,我们使用嵌套数据结构。为嵌套对象创建子模式的工作方式与创建根对象模式非常相似。您可以使用在定义根对象时使用的所有模式关键字,除了$schema
和$id
。它们只需在模式的开头声明即可。
以下示例显示了如何在对象内部创建一个数组类型的数据。在这里,我们将使用一些新的关键字,除了我们之前已经使用过的。
{
"$schema": "https://json-schema.fullstack.org.cn/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "number"
},
"name": {
"description": "name of the employee",
"type": "string",
"minLength":2
},
"age": {
"description": "age of the employee",
"type": "number",
"minimum": 16
},
"hobbies": {
"description": "hobbies of the employee",
"type": "object",
"properties": {
"indoor": {
"type": "array",
"items": {
"description": "List of hobbies",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"outdoor": {
"type": "array",
"items": {
"description": "List of hobbies",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
},
"required": [
"indoor",
"outdoor"
]
}
},
"required": [
"id",
"name",
"age",
"hobbies"
],
"additionalProperties": false
}
在上面的例子中,我们在“hobbies”对象中定义了两个数组字段--indoor
和outdoor
。您可能已经注意到了items
关键字。这个关键字定义了每个项目的属性。
同样,minItems
定义了数组中必须存在的最小项目数,maxItems
定义了数组中可以存在的最大项目数,uniqueItems
唯一标识每个项目。
您还会在子对象中再次看到required
关键字。就像根JSON对象中的required
关键字一样,子对象中的required
关键字指定了子对象中的必填属性。
最后,我们还引入了additionalProperties
。在上面的示例中,它是一个布尔值,取值为false,表示我们无法使用在properties
关键字下未列出的任何其他属性。
然而,additionalProperties
不必一定是布尔值。它也可以是一个对象。例如,在下面的模式中,这个关键字表示我们在这个模式下使用的任何附加属性都必须是字符串类型。
"additionalProperties": { "type": "string" }
虽然上面的示例仅限于一个用例,但JSON模式有无数种用途。JSON模式可以用于验证和强制一致性的一个领域是地理坐标。由于数据性质,接受无效或不一致数据的机会很高。
在下面的示例中,我们可以看到坐标是用数值数据类型表示的。
{
"latitude": 58.858093,
"longitude": 22.294694
}
但我们能用的坐标值是有限的,即值不能超过90或低于负90。因此,让我们创建一个JSON模式来应对这种情况。
{
"$id": "https://example.com/geographical-location.schema.json",
"$schema": "https://json-schema.fullstack.org.cn/draft/2020-12/schema",
"title": "Longitude and Latitude Values",
"description": "A geographical coordinate.",
"required": [ "latitude", "longitude" ],
"type": "object",
"properties": {
"latitude": {
"type": "number",
"minimum": -90,
"maximum": 90
},
"longitude": {
"type": "number",
"minimum": -180,
"maximum": 180
}
}
}
在这里,我们可以看到我们为每个属性使用了minimum
和maximum
关键字来限制可接受值的范围。这不仅解决了数据验证问题,还确保了错误值不会通过。
您可以在文档验证器中使用$jsonSchema
来强制在MongoDB中执行插入和更新操作时指定的模式,包括在MongoDB Atlas中。由于MongoDB以BSON(二进制JSON)存储数据,您可以轻松地将所有数据以JSON格式存储和检索。
MongoDB还允许您强制一个模式来验证您的数据并维护数据结构。我们将使用MongoDB Atlas和MongoDB Compass来演示。
假设我们将以下文档插入名为employees的集合中,该集合位于名为mongodatabase的数据库内。
文档1
{
"id": 7,
"name": "John Doe",
"age": 22,
"hobbies": {
"indoor": [
"Chess"
],
"outdoor": [
"Basketball"
]
}
}
文档2
{
"id": 8,
"name": "Jonathon Smith",
"age": 22
}
文档3
{
"id": 1,
"name": "Jane Doe",
"age": 25,
"hobbies": {
"indoor": [
"Chess"
],
"outdoor": [
"Football"
]
}
}
我们将在MongoDB Compass中强制执行上一节中的模式来验证这些文档。
首先,让我们将我们的集群与Compass连接起来。
mongodb+srv://<username>:<password>@cluster0.9ddm0.mongodb.net/test
将<username>和<password>替换为您创建的数据库用户的用户名和密码。
现在,让我们进入mongodatabase并查看employees集合内的文档。
点击验证选项卡并将以下JSON模式插入以验证我们的文档。以$jsonSchema
关键字开始模式定义。由于我们不需要启动时使用$id和$schema关键字,我们将移除它们。
{
$jsonSchema: {
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "number"
},
"name": {
"description": "name of the employee",
"type": "string",
"minLength":2
},
"age": {
"description": "age of the employee",
"type": "number",
"minimum": 16
},
"hobbies": {
"description": "hobbies of the employee",
"type": "object",
"properties": {
"indoor": {
"type": "array",
"items": {
"description": "List of hobbies",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"outdoor": {
"type": "array",
"items": {
"description": "List of hobbies",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
},
"required": [
"indoor",
"outdoor"
]
}
},
"required": [
"id",
"name",
"age",
"hobbies"
],
"additionalProperties": false
}
}
如果您到目前为止都按照步骤操作,您应该会得到以下结果。
由于我们的模式要求每个文档都有hobbies字段,因此id为8的文档失败,因为它没有包含所需的字段。
您还可以通过遵循设置模式验证规则的文档来设置额外的验证规则。要匹配满足指定JSON Schema的文档,可以使用$jsonSchema
运算符。有关MongoDB JSON Schema文档的详细信息,请参阅该文档。
要了解更多关于MongoDB Atlas的信息,请参阅这篇文章。
到现在为止,你应该已经了解了JSON Schema,为什么它被使用,以及我们如何使用它。我们当然已经扩展了这一概念,以及如何与MongoDB一起使用它,但仍有许多内容需要介绍。
如果您想了解更多关于MongoDB中JSON Schema的信息,我们建议您查阅MongoDB的JSON Schema验证资源。如果您对一般性的JSON Schema验证感兴趣,请访问这篇文章。
是的。JSON Schema被认为是强制执行JSON结构有效性的标准方法。
探索更多文章: