Skip to main content
CheckTown
开发工具

JSON Schema 验证:Schema 草案与规则完全指南

发布于 阅读约 7 分钟
本文目录

什么是 JSON Schema?

JSON Schema 是一套用于标注和校验 JSON 文档的词汇表。它定义了 JSON 文档必须满足的结构、类型和约束。可以把它看作一份契约——Schema 描述了何为有效数据,而校验器则检查文档是否符合这份契约。

JSON Schema 本身就是用 JSON 编写的,因此机器可读且与语言无关。每一种主流编程语言都有校验器支持它(JavaScript/Ajv、Python/jsonschema、Java/everit、Go/gojsonschema),并被广泛用于 API 校验、配置文件和表单生成。

JSON Schema 基础

核心关键字定义了有效 JSON 文档的形态。

  • type——指定允许的 JSON 类型:string、number、integer、boolean、object、array 或 null。这是最基础的约束。
  • properties 和 required——对于对象,“properties” 定义每个字段的 Schema,“required” 列出哪些字段必须存在。未列入 “required” 的字段默认为可选。
  • enum 和 const——“enum” 将值限定在一组固定的选项之中,而 “const” 将其限定为唯一的精确值。适用于状态字段、分类和配置选项。
  • pattern 和 format——“pattern” 用正则表达式校验字符串。“format” 提供语义化校验,例如 “email”、“uri”、“date-time” 和 “ipv4”,无需正则表达式。

这些基础关键字覆盖了大多数校验需求。一个简单的 Schema 可以定义一个对象类型,包含必填的 “name”(string)和可选的 “age”(integer,最小值为 0)属性。

高级 Schema 特性

对于复杂的校验需求,JSON Schema 提供了组合、引用和条件逻辑。

  • $ref 引用——通过 $ref 引用来复用 Schema 定义。可指向同一文档内的定义($ref: #/$defs/Address)或外部文件,从而消除大型 Schema 中的重复内容。
  • allOf / anyOf / oneOf——用于组合多个 Schema 的组合关键字。“allOf” 要求所有子 Schema 都匹配,“anyOf” 要求至少匹配其一,“oneOf” 要求恰好匹配其一。适用于多态类型。
  • if / then / else——根据数据值应用不同校验规则的条件 Schema。例如,若国家为 “US”,则邮政编码必须匹配 5 位数字的模式,否则允许任意格式。
  • additionalProperties——控制对象是否可以包含未列在 “properties” 中的属性。设为 false 表示严格校验,或设为一个 Schema 来约束额外的属性。

免费试用 —— 无需注册

校验 JSON Schema →

Schema 草案版本

JSON Schema 历经多个草案版本演进,每一版都新增特性并优化既有行为。

  • Draft-04——第一个被广泛采用的版本。引入了 $ref、以数组形式表示的 required 以及基础的校验关键字。至今仍用于许多遗留系统和 OpenAPI 3.0。
  • Draft-06——新增了 const 关键字、propertyNames、用于数组的 contains,以及布尔型 Schema(将 true/false 作为有效的 Schema)。虽小但实用的增补。
  • Draft-07——新增了 if/then/else 条件逻辑、readOnly/writeOnly 标注以及内容编码关键字。是当今最流行的草案版本。
  • 2019-09(Draft 2019-09)——重大重构。引入了 $defs(取代 definitions)、$anchor、unevaluatedProperties 以及词汇表系统,更适合大规模 Schema 设计。
  • 2020-12(Draft 2020-12)——最新的稳定草案。改进了动态引用,新增了用于元组校验的 prefixItems(取代以数组形式表示的 items),并优化了输出格式。推荐用于新项目。

常见使用场景

凡是需要校验或记录 JSON 数据的地方,都会用到 JSON Schema。

  • API 校验——在 Express/Fastify 中间件中,根据 Schema 校验请求体和查询参数。OpenAPI/Swagger 规范内嵌 JSON Schema 用于定义 API 契约。
  • 配置校验——在启动时校验应用配置文件(JSON,或由 YAML 转换而来的 JSON)。在拼写错误和缺失字段引发运行时错误之前就将其捕获。
  • 表单生成——react-jsonschema-form 和 vue-jsonschema-form 等工具可根据 JSON Schema 定义自动生成 HTML 表单,包括校验规则和 UI 控件。
  • 代码生成——根据 JSON Schema 定义生成 TypeScript 接口、Go 结构体或 Python dataclass,使类型与 API 契约保持同步。

常见的校验错误

在根据 Schema 校验 JSON 时,以下是你最常遇到的错误。

  • 类型不匹配——值的类型与 Schema 的 “type” 约束不符。常见示例:本应是 number 却出现 string、可空字段之外的字段出现 null,或本应是数组的地方出现对象。
  • 缺失必填字段——JSON 对象缺少 “required” 数组中所列的属性。校验器会报告具体缺失的是哪个字段。
  • 模式校验失败——字符串值不匹配 “pattern” 正则表达式。这通常会捕获无效的邮箱格式、电话号码,或不符合预期模式的自定义标识符。
  • $ref 解析失败——Schema 通过 $ref 引用了另一个无法找到的 Schema。当 $defs 条目缺失、路径错误或外部 Schema 文件不可访问时,就会发生这种情况。

常见问题

新项目应该使用哪个 JSON Schema 草案?

除非有特定约束,新项目应使用 Draft 2020-12。它拥有最多的特性(用于元组的 prefixItems、unevaluatedProperties、动态引用)以及最优的规范质量。如果你需要兼容 OpenAPI 3.0,则使用 Draft-04。如果你需要最广泛的库支持,Draft-07 是最稳妥的选择——几乎每个校验器都支持它。

如何在多个文件之间复用 Schema?

使用 $ref 通过 URI 引用 Schema。对于本地定义,将可复用的 Schema 放在同一文件的 $defs 之下,并用 $ref: '#/$defs/SchemaName' 引用它们。对于跨文件引用,使用相对 URI($ref: './address.json')或绝对 URI。大多数校验器都同时支持本地和远程的 $ref 解析。

JSON Schema 能校验嵌套对象吗?

可以。在父对象的 “properties” 中定义嵌套的 Schema。每个嵌套属性都可以拥有自己的类型、必填字段和校验规则。对于深层嵌套的结构,使用 $ref 可让 Schema 保持可读性。嵌套深度没有限制——校验器会递归地校验每一层。

相关工具