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

这篇文章有帮助吗?

保持更新

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

无垃圾邮件,随时退订。

合作推荐

赞助这篇文章

把你的产品放到这个开发者主题旁边,并追踪点击效果。

咨询文章赞助

本站使用 Cookie 进行流量分析与广告展示。继续浏览即视为同意。 隐私政策