JSON Schema: What It Is and How to Use It

Learn JSON Schema from scratch. Understand types, constraints, composition keywords, $ref, and see a complete practical example for API validation.

JSONTech 团队February 1, 202511 min read

什么是 JSON Schema?

JSON Schema 是一种词汇,允许您描述 JSON 数据的结构。可以将其视为一种合同:它定义了 JSON 文档应具有的字段、这些字段必须是什么类型,以及它们必须满足的约束。当文档符合其模式时,它是 有效的。当不符合时,验证器会告诉您具体出了什么问题。

这很重要,因为 JSON 本身在结构上是宽松的。 JSON 规范 中没有任何内容阻止 API 返回一个字符串而您期望的是一个数字,或者省略一个必需字段。JSON Schema 解决了这个问题。

为什么 JSON Schema 重要

  • API 合同。 精确地定义您的 API 期望和返回的内容。客户端和服务器团队可以独立验证有效负载。
  • 数据验证。 在边界捕获格式错误的数据——在表单提交、Webhook 有效负载、配置文件或数据库写入中。
  • 文档。 模式是机器可读的文档。工具可以从中生成可读的文档、表单,甚至模拟数据。
  • 代码生成。 直接从您的模式生成 TypeScript 接口、Go 结构或 Python 数据类。

基础知识:类型、属性、必需

每个 JSON Schema 都以 type 开始。这告诉验证器在顶层预期什么类型的值:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "用户的全名"
    },
    "age": {
      "type": "integer",
      "description": "年龄(以年为单位)"
    }
  },
  "required": ["name"]
}

该模式表示:“我期望一个 JSON 对象,具有一个 name 属性(字符串,必需)和一个可选的 age 属性(整数)。”任何缺少 name 或提供非字符串 name 的对象都是无效的。

所有 JSON Schema 类型

JSON Schema 支持七种基本类型。以下是每种类型及其最小模式示例:

类型有效值模式示例
string"hello"""{"type": "string"}
number3.14-10{"type": "number"}
integer42-7{"type": "integer"}
booleantruefalse{"type": "boolean"}
nullnull{"type": "null"}
object{"key": "value"}{"type": "object", "properties": {...}}
array[1, 2, 3]{"type": "array", "items": {...}}

对象详细信息

使用 properties 定义预期字段,使用 required 列出必需字段,使用 additionalProperties 控制是否允许额外字段:

{
  "type": "object",
  "properties": {
    "id": { "type": "integer" },
    "email": { "type": "string", "format": "email" }
  },
  "required": ["id", "email"],
  "additionalProperties": false
}

additionalProperties: false 设置为拒绝任何包含未在 properties 中列出的键的对象。这对于严格的 API 合同非常有用。

数组详细信息

使用 items 定义每个元素应是什么样子,使用 minItems / maxItems 限制长度:

{
  "type": "array",
  "items": { "type": "string" },
  "minItems": 1,
  "maxItems": 10,
  "uniqueItems": true
}

这接受一个包含 1 到 10 个唯一字符串的数组。空数组或包含重复项的数组将无法通过验证。

约束和验证关键字

除了基本类型,JSON Schema 还为每种类型提供了细粒度的约束:

字符串约束

关键字描述示例
minLength最小字符数"minLength": 1
maxLength最大字符数"maxLength": 255
pattern字符串必须匹配的正则表达式"pattern": "^[A-Z]{2}\\\\d{4}$"
format语义格式提示"format": "email"
enum允许的值"enum": ["active", "inactive"]

数字约束

关键字描述示例
minimum值必须 >= 这个"minimum": 0
maximum值必须 <= 这个"maximum": 100
exclusiveMinimum值必须 > 这个"exclusiveMinimum": 0
exclusiveMaximum值必须 < 这个"exclusiveMaximum": 1000
multipleOf值必须能被这个整除"multipleOf": 0.01

组合模式:allOf、anyOf、oneOf、not

组合关键字允许您从简单模式构建复杂模式:

  • allOf — 数据必须符合 所有 列出的模式。用于组合多个约束或扩展基本模式。
  • anyOf — 数据必须符合 至少一个 列出的模式。适用于接受多种格式的字段。
  • oneOf — 数据必须符合 恰好一个 列出的模式。适用于区分联合。
  • not — 数据必须 符合给定的模式。
{
  "oneOf": [
    {
      "type": "object",
      "properties": {
        "type": { "const": "email" },
        "address": { "type": "string", "format": "email" }
      },
      "required": ["type", "address"]
    },
    {
      "type": "object",
      "properties": {
        "type": { "const": "phone" },
        "number": { "type": "string", "pattern": "^\\\\+?[0-9]{7,15}$" }
      },
      "required": ["type", "number"]
    }
  ]
}

该模式接受电子邮件联系人或电话联系人,但不能同时接受——这是一种干净的建模标记联合的方式。

使用 $ref 的可重用性

模式很快会变得重复。$ref 关键字允许您引用可重用的定义:

{
  "type": "object",
  "properties": {
    "billing_address": { "$ref": "#/$defs/address" },
    "shipping_address": { "$ref": "#/$defs/address" }
  },
  "$defs": {
    "address": {
      "type": "object",
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "zip": { "type": "string", "pattern": "^[0-9]{5}(-[0-9]{4})?$" }
      },
      "required": ["street", "city", "zip"]
    }
  }
}

billing_addressshipping_address 共享相同的结构而无需重复。$defs 部分(在旧草案中称为 definitions)是存储可重用模式的常规位置。

完整示例:用户注册验证

以下是一个用于验证用户注册有效负载的真实模式。它使用了我们所涵盖的大多数功能:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "用户注册",
  "description": "POST /api/register 端点的模式",
  "type": "object",
  "properties": {
    "username": {
      "type": "string",
      "minLength": 3,
      "maxLength": 30,
      "pattern": "^[a-zA-Z0-9_]+$",
      "description": "字母数字用户名,3-30 个字符"
    },
    "email": {
      "type": "string",
      "format": "email",
      "maxLength": 254
    },
    "password": {
      "type": "string",
      "minLength": 8,
      "maxLength": 128,
      "description": "至少 8 个字符"
    },
    "age": {
      "type": "integer",
      "minimum": 13,
      "maximum": 150
    },
    "role": {
      "type": "string",
      "enum": ["user", "moderator"],
      "default": "user"
    },
    "acceptedTerms": {
      "type": "boolean",
      "const": true
    },
    "tags": {
      "type": "array",
      "items": { "type": "string", "maxLength": 20 },
      "maxItems": 5,
      "uniqueItems": true
    }
  },
  "required": ["username", "email", "password", "acceptedTerms"],
  "additionalProperties": false
}

请注意,每个字段都有明确的、可强制执行的约束。验证器将拒绝 2 个字符的用户名、低于 13 岁的年龄、重复的标签或任何未在模式中列出的额外字段。

尝试一下: 粘贴任何 JSON 并使用我们的 JSON Schema Generator 自动生成模式。

JSON Schema 在现实世界中的应用

OpenAPI / Swagger

OpenAPI 使用 JSON Schema(带有一些扩展)来定义请求体、响应形状和查询参数。OpenAPI 规范中的每个 schema 块都是一个 JSON Schema。如果您编写 OpenAPI 文档,您已经在编写 JSON Schema。

表单验证

react-jsonschema-formajv(JavaScript 中最快的 JSON Schema 验证器)这样的库使用模式在运行时生成和验证表单。只需定义一次模式,后端和前端都可以根据相同的规则进行验证。

数据库模式

MongoDB 在集合级别支持 JSON Schema 验证。您可以设置一个 $jsonSchema 验证器,拒绝任何不符合您的模式的文档的插入或更新。

配置文件

VS Code、ESLint 和许多其他工具使用 JSON Schema 验证其配置文件。当您编辑 tsconfig.json 时获得的自动补全?它是由 JSON Schema 提供支持的。

草案版本比较

JSON Schema 经过多个草案的演变。以下是您将遇到的草案:

草案年份主要新增内容状态
Draft-042013核心词汇,$ref,基本类型过时(仍广泛使用)
Draft-062017constcontainspropertyNames过时
Draft-072018if/then/elsereadOnlywriteOnly广泛支持
2019-092019$defsunevaluatedPropertiesdependentRequired主要验证器支持
2020-122020prefixItems(替代元组验证),动态 $ref当前 / 推荐

对于新项目,请使用 2020-12。如果您需要与现有工具的最大兼容性,Draft-07 是安全的选择——它几乎具有普遍的库支持。

常见错误及避免方法

  • 忘记 requiredproperties 下定义的属性默认是可选的。如果字段必须存在,请在 required 中列出它。
  • 混淆 numberinteger number 接受小数;integer 不接受。对于 ID、计数和其他整数值,请使用 integer
  • 过早过度约束。 从捕获真实错误的最小模式开始。您可以随时收紧约束——放宽它们是一个破坏性更改。
  • 不使用 $ref 在多个地方重复相同的子模式是维护噩梦。将共享结构提取到 $defs 中。
  • 忽视 format 验证。 默认情况下,大多数验证器将 format 视为注释,而不是约束。您需要显式启用格式验证(例如,ajv.addFormat() 或传递 { validateFormats: true })。

尝试一下: 使用我们的 JSON Schema Generator 从任何 JSON 示例生成模式,然后自定义约束以匹配您的要求。

相关工具