DevToolBox免费
博客

JSON Schema 完全指南:验证、类型和最佳实践

15 分钟作者 DevToolBox

JSON Schema 是描述 JSON 数据结构、约束和验证规则的标准方式。无论你需要从 JSON 创建 Schema、验证 API 载荷,还是生成文档,JSON Schema 都提供了人类和机器都能理解的声明式词汇。本指南涵盖了从基础到高级特性,包括 $ref、条件模式,以及 Python 和 JavaScript 中的代码级验证。

试用我们免费的 JSON 转 JSON Schema 生成器。

什么是 JSON Schema?

JSON Schema 是一种基于 JSON 的词汇,允许你对 JSON 文档进行注解和验证。它定义了预期的数据类型、必填属性、值约束和结构模式。

JSON Schema 广泛用于 API 请求/响应验证(OpenAPI/Swagger)、配置文件验证、UI 框架中的表单生成、数据库文档验证(MongoDB)和基础设施即代码工具(Terraform、Kubernetes)。

JSON Schema 规范已经历多个草案版本。Draft-07 是支持最广泛的版本,Draft 2020-12 是最新的稳定版本。

JSON Schema 草案版本:该用哪个?

JSON Schema 经历了多个草案版本的发展:

草案年份新增关键特性适用场景
Draft-042013核心词汇、$ref遗留系统
Draft-062017constcontains中等兼容性
Draft-072018if/then/elsereadOnly大多数项目(最广泛支持)
2019-092019$anchorunevaluatedProperties高级模式
2020-122020$dynamicRefprefixItems使用最新规范的新项目

对于大多数项目,Draft-07 提供了功能和库支持之间的最佳平衡。

如何从 JSON 创建 JSON Schema

从 JSON 创建 JSON Schema 包括分析 JSON 样本文档并生成描述其结构的模式:

  1. 识别顶层类型:确定根是对象、数组还是原始值。
  2. 定义属性:为 JSON 对象中的每个键创建属性定义。
  3. 设置必填字段:将属性名添加到 "required" 数组。
  4. 添加约束:使用 minLengthpatternenum 等关键字。
  5. 处理嵌套对象:定义内联模式或使用 $ref 引用共享定义。
  6. 处理数组:使用 "items" 定义数组元素的模式。
  7. 添加元数据:包括 $schematitledescription
// Example: Sample JSON input
{
  "id": 1,
  "name": "Alice Johnson",
  "email": "alice@example.com",
  "age": 28,
  "is_active": true,
  "roles": ["admin", "editor"],
  "address": {
    "street": "123 Main St",
    "city": "Springfield",
    "zip": "62704"
  }
}

// Generated JSON Schema (Draft-07)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "User",
  "type": "object",
  "properties": {
    "id": { "type": "integer" },
    "name": { "type": "string" },
    "email": { "type": "string", "format": "email" },
    "age": { "type": "integer", "minimum": 0 },
    "is_active": { "type": "boolean" },
    "roles": {
      "type": "array",
      "items": { "type": "string" }
    },
    "address": {
      "type": "object",
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "zip": { "type": "string", "pattern": "^[0-9]{5}$" }
      },
      "required": ["street", "city", "zip"]
    }
  },
  "required": ["id", "name", "email", "is_active"]
}

JSON Schema 核心关键字

JSON Schema 使用丰富的关键字来描述数据:

类别关键字用途
类型typeenumconst定义允许的类型和值
字符串minLengthmaxLengthpatternformat约束字符串值
数字minimummaximummultipleOf约束数值范围
对象propertiesrequiredadditionalProperties定义对象形状
数组itemsminItemsuniqueItems定义数组约束
组合allOfanyOfoneOfnot组合多个模式
条件ifthenelse条件验证
引用$ref$defs复用模式组件

代码示例:使用 JSON Schema 验证 JSON

Python:jsonschema 库

jsonschema 是 Python 中最流行的 JSON Schema 验证库,支持 Draft-04 到 Draft 2020-12:

import json
from jsonschema import validate, ValidationError, Draft7Validator

# Define the schema
schema = {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
        "name": {"type": "string", "minLength": 1},
        "email": {"type": "string", "format": "email"},
        "age": {"type": "integer", "minimum": 0, "maximum": 150},
        "roles": {
            "type": "array",
            "items": {"type": "string", "enum": ["admin", "editor", "viewer"]},
            "minItems": 1,
            "uniqueItems": True
        }
    },
    "required": ["name", "email"],
    "additionalProperties": False
}

# Valid data
valid_data = {
    "name": "Alice",
    "email": "alice@example.com",
    "age": 28,
    "roles": ["admin", "editor"]
}

# Validate
try:
    validate(instance=valid_data, schema=schema)
    print("Validation passed!")
except ValidationError as e:
    print(f"Validation failed: {e.message}")

# Collect all errors at once
invalid_data = {"name": "", "email": "not-an-email", "age": -5}
validator = Draft7Validator(schema)
errors = list(validator.iter_errors(invalid_data))
for error in errors:
    print(f"Error at {list(error.path)}: {error.message}")

JavaScript/Node.js:Ajv

Ajv 是 JavaScript 生态中最快和最广泛使用的 JSON Schema 验证器:

import Ajv from "ajv";
import addFormats from "ajv-formats";

const ajv = new Ajv({ allErrors: true });
addFormats(ajv); // Adds "email", "uri", "date-time", etc.

const schema = {
  type: "object",
  properties: {
    name: { type: "string", minLength: 1 },
    email: { type: "string", format: "email" },
    age: { type: "integer", minimum: 0 },
    tags: {
      type: "array",
      items: { type: "string" },
      uniqueItems: true
    },
    address: {
      type: "object",
      properties: {
        street: { type: "string" },
        city: { type: "string" },
        country: { type: "string", default: "US" }
      },
      required: ["street", "city"]
    }
  },
  required: ["name", "email"],
  additionalProperties: false,
};

// Compile schema once, validate many times (fast!)
const validate = ajv.compile(schema);

const data = {
  name: "Bob",
  email: "bob@example.com",
  age: 35,
  tags: ["developer", "writer"],
  address: { street: "456 Oak Ave", city: "Portland" }
};

if (validate(data)) {
  console.log("Valid!");
} else {
  console.log("Errors:", validate.errors);
  // Each error: { keyword, dataPath, message, params }
}

使用 $ref 实现可复用的 Schema 组件

随着 Schema 的增长,你会发现重复的模式。$ref 关键字允许你引用在其他地方定义的模式,保持 DRY 原则。

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "billing_address": { "$ref": "#/definitions/Address" },
    "shipping_address": { "$ref": "#/definitions/Address" },
    "user": { "$ref": "#/definitions/User" }
  },
  "definitions": {
    "Address": {
      "type": "object",
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "state": { "type": "string", "minLength": 2, "maxLength": 2 },
        "zip": { "type": "string", "pattern": "^[0-9]{5}(-[0-9]{4})?$" }
      },
      "required": ["street", "city", "state", "zip"]
    },
    "User": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "email": { "type": "string", "format": "email" }
      },
      "required": ["name", "email"]
    }
  }
}

$ref 使用 JSON Pointer 语法引用定义。Draft-07 中定义存储在 "definitions" 下,Draft 2020-12 中标准位置是 "$defs"

广泛使用 $ref 可以将你的模式从单体文档转变为模块化架构,在 OpenAPI 规范中尤其有价值。

必填字段和默认值

"required" 关键字是必须出现在有效 JSON 对象中的属性名数组。

"default" 关键字为未提供的属性指定默认值。注意规范不强制验证器填充默认值,具体行为取决于库的实现。

常见验证模式

以下是实际 API 开发中常见的 JSON Schema 验证模式:

邮箱验证:使用 "format": "email" 进行基本检查。

日期时间验证:使用 "format": "date-time" 验证 ISO 8601 时间戳。

枚举值:使用 "enum" 限制字段为固定值集合。

条件模式:使用 if/then/else 根据数据值应用不同的验证规则。

// Conditional schema: if/then/else (Draft-07+)
{
  "type": "object",
  "properties": {
    "account_type": { "enum": ["personal", "business"] },
    "name": { "type": "string" }
  },
  "required": ["account_type", "name"],
  "if": {
    "properties": { "account_type": { "const": "business" } }
  },
  "then": {
    "properties": {
      "company_name": { "type": "string", "minLength": 1 },
      "tax_id": { "type": "string", "pattern": "^[0-9]{2}-[0-9]{7}$" }
    },
    "required": ["company_name", "tax_id"]
  },
  "else": {
    "properties": {
      "date_of_birth": { "type": "string", "format": "date" }
    }
  }
}

JSON Schema 最佳实践

从 Draft-07 开始:拥有最广泛的库支持,包含条件验证。

谨慎使用 additionalProperties: false:它会拒绝未列出的属性,但会破坏 allOf 组合。

使用 $ref$defs 组织:提取共享模式为可复用定义。

添加 title 和 description:生成人类可读的文档并改善 IDE 自动补全。

使用 format 关键字"format": "uri""format": "email" 传达语义意图。

使用多个验证器测试:不同库对边界情况的解释不同。

版本化 Schema:使用 $id 和版本号 URL 支持模式演进。

相关工具:JSON 格式化器JSON 验证器JSON 转 TypeScript

JSON to JSON SchemaJSON FormatterJSON ValidatorJSON to TypeScript

常见问题

如何从现有 JSON 文件生成 JSON Schema?

使用我们的免费在线 JSON 转 JSON Schema 工具:粘贴 JSON,即时生成包含推断类型和必填字段的 Draft-07 模式。编程方式可使用 Python 的 genson 或 Node.js 的 json-schema-generator。

JSON Schema Draft-07 和 Draft 2020-12 有什么区别?

Draft 2020-12 引入了 $dynamicRef、prefixItems 替代数组形式的 items、$vocabulary 以及默认将 format 视为注解。Draft-07 有更广泛的库支持,满足大多数使用场景。

JSON Schema 能验证嵌套对象和数组吗?

可以。使用 properties 和内联对象模式处理嵌套对象,使用 items 和对象模式处理对象数组。可以任意深度嵌套,使用 $ref 引用共享结构避免重复。

如何使 JSON Schema 字段可选?

从 required 数组中省略字段名即可。在 properties 中定义但不在 required 中列出的属性是可选的。

Python 和 JavaScript 最好的 JSON Schema 验证器是什么?

Python 推荐 jsonschema(支持所有草案),JavaScript 推荐 Ajv(最快且功能最完整),两者都在积极维护。

JSON Schema 是验证、文档化和强制执行 JSON 数据合约的必备工具。使用我们的免费在线工具即时生成 JSON Schema,并参考本指南了解最佳实践。

使用我们的免费在线工具即时从 JSON 生成 JSON Schema。

Related Developer Tools and Guides

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

{ }JSON FormatterJSON ValidatorJSON Beautifier

相关文章

JSON Schema 验证:类型、工具与最佳实践

关于 JSON Schema 验证的一切:从基本类型到高级模式、验证库以及与 TypeScript 和 API 的集成。

JSON 格式化与验证:在线美化、修复 JSON 完全指南

免费在线 JSON 格式化和验证工具。美化 JSON、查找语法错误,附 JavaScript 和 Python 代码示例。

JSON vs YAML vs TOML:你应该用哪种配置格式?

比较 JSON、YAML 和 TOML 配置格式,了解语法、特性和优缺点,选择适合你项目的格式。