JSON Schema

什么是 JSON Schema?

JSON Schema 是一种基于 JSON 的格式,用于描述 JSON 数据的结构。它允许你验证 JSON 文档、提供交互式文档,并控制客户端和服务器之间的数据交互。

数据验证

验证 JSON 数据的结构和内容

📋

文档生成

自动生成 API 文档

🔄

数据交互

控制客户端和服务器数据交互

🔧

代码生成

根据 Schema 生成数据模型

简单示例

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/person.schema.json",
  "title": "人员信息",
  "description": "一个人的基本信息",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "人员姓名"
    },
    "age": {
      "type": "integer",
      "minimum": 0,
      "maximum": 150
    }
  },
  "required": ["name"]
}

基本概念

Schema 的核心作用

  • 验证:确保 JSON 数据符合预期的结构
  • 文档:清晰地描述数据的格式和约束
  • 超媒体:描述 Web API 的交互模式
  • 代码生成:根据 Schema 自动生成数据模型

Schema 版本

JSON Schema 有多个版本,推荐使用最新版本:

版本 草案 主要特性
Draft 4 2013 基础验证功能
Draft 6 2017 改进的数值验证
Draft 7 2018 条件验证、内容编码
Draft 2020-12 2020 最新标准,功能最全
提示: 在实际项目中,建议使用 Draft 2020-12 版本,因为它是最新且功能最完整的标准。

基本语法

Schema 声明

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/product.schema.json",
  "title": "产品信息",
  "description": "一个产品的完整信息",
  "type": "object"
}

基本类型验证

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "stringField": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "numberField": {
      "type": "number",
      "minimum": 0,
      "maximum": 100
    },
    "integerField": {
      "type": "integer",
      "minimum": 1
    },
    "booleanField": {
      "type": "boolean"
    },
    "nullField": {
      "type": "null"
    }
  },
  "required": ["stringField", "integerField"]
}

数组验证

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "tags": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      },
      "minItems": 1,
      "maxItems": 10,
      "uniqueItems": true
    },
    "scores": {
      "type": "array",
      "items": {
        "type": "number",
        "minimum": 0,
        "maximum": 100
      },
      "minItems": 3,
      "maxItems": 5
    }
  }
}

验证关键字

类型相关关键字

关键字 描述 示例
type 数据类型 "type": "string"
enum 枚举值 "enum": ["A", "B", "C"]
const 固定值 "const": "fixed-value"

数值验证关键字

关键字 描述 示例
minimum 最小值 "minimum": 0
maximum 最大值 "maximum": 100
exclusiveMinimum 排除最小值 "exclusiveMinimum": 0
exclusiveMaximum 排除最大值 "exclusiveMaximum": 100
multipleOf 倍数 "multipleOf": 0.5

字符串验证关键字

关键字 描述 示例
minLength 最小长度 "minLength": 1
maxLength 最大长度 "maxLength": 100
pattern 正则表达式 "pattern": "^[A-Za-z]+$"
format 格式验证 "format": "email"

对象验证关键字

关键字 描述 示例
properties 属性定义 "properties": {"name": {...}}
required 必需属性 "required": ["name", "age"]
additionalProperties 允许额外属性 "additionalProperties": false
minProperties 最小属性数 "minProperties": 1
maxProperties 最大属性数 "maxProperties": 10

数组验证关键字

关键字 描述 示例
items 数组项定义 "items": {"type": "string"}
minItems 最小项数 "minItems": 1
maxItems 最大项数 "maxItems": 10
uniqueItems 唯一项 "uniqueItems": true
contains 必须包含 "contains": {"type": "string"}

复杂验证示例

用户注册表单

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/user-registration.schema.json",
  "title": "用户注册信息",
  "description": "用户注册时提交的信息",
  "type": "object",
  "properties": {
    "username": {
      "type": "string",
      "minLength": 3,
      "maxLength": 20,
      "pattern": "^[a-zA-Z0-9_]+$",
      "description": "用户名,只能包含字母、数字和下划线"
    },
    "email": {
      "type": "string",
      "format": "email",
      "description": "用户邮箱地址"
    },
    "password": {
      "type": "string",
      "minLength": 8,
      "pattern": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).+$",
      "description": "密码必须包含大小写字母和数字"
    },
    "age": {
      "type": "integer",
      "minimum": 18,
      "maximum": 120,
      "description": "用户年龄"
    },
    "interests": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      },
      "minItems": 1,
      "maxItems": 10,
      "uniqueItems": true,
      "description": "用户兴趣列表"
    },
    "settings": {
      "type": "object",
      "properties": {
        "newsletter": {
          "type": "boolean",
          "description": "是否订阅新闻邮件"
        },
        "theme": {
          "type": "string",
          "enum": ["light", "dark", "auto"],
          "default": "auto"
        }
      },
      "additionalProperties": false
    }
  },
  "required": ["username", "email", "password"],
  "additionalProperties": false
}

产品目录

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/product-catalog.schema.json",
  "title": "产品目录",
  "description": "电子商务网站的产品目录",
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id": {
        "type": "string",
        "pattern": "^[A-Z0-9]{8}$",
        "description": "产品唯一标识符"
      },
      "name": {
        "type": "string",
        "minLength": 1,
        "maxLength": 100,
        "description": "产品名称"
      },
      "description": {
        "type": "string",
        "maxLength": 1000,
        "description": "产品描述"
      },
      "price": {
        "type": "number",
        "minimum": 0,
        "multipleOf": 0.01,
        "description": "产品价格"
      },
      "currency": {
        "type": "string",
        "enum": ["USD", "EUR", "CNY", "JPY"],
        "default": "USD"
      },
      "categories": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "minItems": 1,
        "description": "产品分类"
      },
      "inventory": {
        "type": "object",
        "properties": {
          "stock": {
            "type": "integer",
            "minimum": 0,
            "description": "库存数量"
          },
          "reserved": {
            "type": "integer",
            "minimum": 0,
            "description": "预留数量"
          }
        },
        "required": ["stock"]
      },
      "attributes": {
        "type": "object",
        "additionalProperties": {
          "type": ["string", "number", "boolean"]
        },
        "description": "产品额外属性"
      }
    },
    "required": ["id", "name", "price", "categories"]
  },
  "minItems": 0
}

条件验证

if-then-else 结构

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "country": {
      "type": "string",
      "enum": ["US", "CA", "CN", "JP"]
    },
    "postal_code": {
      "type": "string"
    }
  },
  "required": ["country", "postal_code"],
  "if": {
    "properties": {
      "country": { "const": "US" }
    }
  },
  "then": {
    "properties": {
      "postal_code": {
        "type": "string",
        "pattern": "^[0-9]{5}(-[0-9]{4})?$"
      }
    }
  },
  "else": {
    "if": {
      "properties": {
        "country": { "const": "CA" }
      }
    },
    "then": {
      "properties": {
        "postal_code": {
          "type": "string",
          "pattern": "^[A-Z][0-9][A-Z] [0-9][A-Z][0-9]$"
        }
      }
    }
  }
}

依赖验证

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "payment_method": {
      "type": "string",
      "enum": ["credit_card", "paypal", "bank_transfer"]
    },
    "credit_card": {
      "type": "object",
      "properties": {
        "number": { "type": "string" },
        "expiry": { "type": "string" },
        "cvv": { "type": "string" }
      },
      "required": ["number", "expiry", "cvv"]
    },
    "paypal_email": {
      "type": "string",
      "format": "email"
    },
    "bank_account": {
      "type": "object",
      "properties": {
        "account_number": { "type": "string" },
        "routing_number": { "type": "string" }
      },
      "required": ["account_number", "routing_number"]
    }
  },
  "required": ["payment_method"],
  "allOf": [
    {
      "if": {
        "properties": {
          "payment_method": { "const": "credit_card" }
        }
      },
      "then": {
        "required": ["credit_card"]
      }
    },
    {
      "if": {
        "properties": {
          "payment_method": { "const": "paypal" }
        }
      },
      "then": {
        "required": ["paypal_email"]
      }
    },
    {
      "if": {
        "properties": {
          "payment_method": { "const": "bank_transfer" }
        }
      },
      "then": {
        "required": ["bank_account"]
      }
    }
  ]
}

组合模式

allOf - 必须满足所有条件

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "allOf": [
    {
      "type": "object",
      "properties": {
        "name": { "type": "string" }
      },
      "required": ["name"]
    },
    {
      "type": "object",
      "properties": {
        "age": { "type": "integer", "minimum": 0 }
      },
      "required": ["age"]
    }
  ]
}

anyOf - 满足任意一个条件

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "anyOf": [
    {
      "type": "string",
      "minLength": 1
    },
    {
      "type": "number",
      "minimum": 0
    },
    {
      "type": "boolean"
    }
  ]
}

oneOf - 必须满足且仅满足一个条件

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "oneOf": [
    {
      "type": "object",
      "properties": {
        "email": { "type": "string", "format": "email" }
      },
      "required": ["email"]
    },
    {
      "type": "object",
      "properties": {
        "phone": { "type": "string", "pattern": "^\\+?[\\d\\s-()]+$" }
      },
      "required": ["phone"]
    }
  ]
}

not - 排除特定模式

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "not": {
    "type": "null"
  }
}

引用和复用

使用 $ref 引用

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/schemas/person.json",
  "title": "人员信息",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1
    },
    "age": {
      "type": "integer",
      "minimum": 0
    },
    "address": {
      "$ref": "#/$defs/address"
    }
  },
  "required": ["name"],
  "$defs": {
    "address": {
      "type": "object",
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "country": { "type": "string" }
      },
      "required": ["street", "city", "country"]
    }
  }
}

外部引用

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/schemas/order.json",
  "title": "订单信息",
  "type": "object",
  "properties": {
    "order_id": {
      "type": "string"
    },
    "customer": {
      "$ref": "https://example.com/schemas/person.json"
    },
    "items": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/orderItem"
      }
    }
  },
  "$defs": {
    "orderItem": {
      "type": "object",
      "properties": {
        "product_id": { "type": "string" },
        "quantity": { "type": "integer", "minimum": 1 }
      },
      "required": ["product_id", "quantity"]
    }
  }
}

实际应用

JavaScript 验证示例

// 使用 ajv 验证器
const Ajv = require('ajv');
const ajv = new Ajv();

// 定义 schema
const userSchema = {
  type: 'object',
  properties: {
    name: { type: 'string', minLength: 1 },
    email: { type: 'string', format: 'email' },
    age: { type: 'integer', minimum: 0 }
  },
  required: ['name', 'email'],
  additionalProperties: false
};

// 编译 schema
const validate = ajv.compile(userSchema);

// 验证数据
const validData = {
  name: '张三',
  email: 'zhangsan@example.com',
  age: 30
};

const invalidData = {
  name: '',
  email: 'invalid-email',
  age: -5
};

console.log('有效数据验证:', validate(validData)); // true
console.log('无效数据验证:', validate(invalidData)); // false
console.log('验证错误:', validate.errors);

Python 验证示例

from jsonschema import validate, ValidationError

# 定义 schema
user_schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string", "minLength": 1},
        "email": {"type": "string", "format": "email"},
        "age": {"type": "integer", "minimum": 0}
    },
    "required": ["name", "email"],
    "additionalProperties": False
}

# 验证数据
valid_data = {
    "name": "张三",
    "email": "zhangsan@example.com",
    "age": 30
}

invalid_data = {
    "name": "",
    "email": "invalid-email",
    "age": -5
}

try:
    validate(instance=valid_data, schema=user_schema)
    print("有效数据验证通过")
except ValidationError as e:
    print(f"验证错误: {e}")

try:
    validate(instance=invalid_data, schema=user_schema)
    print("无效数据验证通过")
except ValidationError as e:
    print(f"验证错误: {e}")

PHP 验证示例

<?php
// 使用 justinrainbow/json-schema
require 'vendor/autoload.php';

use JsonSchema\Validator;
use JsonSchema\Constraints\Constraint;

// 定义 schema
$userSchema = (object)[
    'type' => 'object',
    'properties' => (object)[
        'name' => (object)[
            'type' => 'string',
            'minLength' => 1
        ],
        'email' => (object)[
            'type' => 'string',
            'format' => 'email'
        ],
        'age' => (object)[
            'type' => 'integer',
            'minimum' => 0
        ]
    ],
    'required' => ['name', 'email'],
    'additionalProperties' => false
];

// 验证数据
$validator = new Validator();

$validData = (object)[
    'name' => '张三',
    'email' => 'zhangsan@example.com',
    'age' => 30
];

$invalidData = (object)[
    'name' => '',
    'email' => 'invalid-email',
    'age' => -5
];

$validator->validate($validData, $userSchema, Constraint::CHECK_MODE_TYPE_CAST);
if ($validator->isValid()) {
    echo "有效数据验证通过\n";
} else {
    echo "验证错误:\n";
    foreach ($validator->getErrors() as $error) {
        echo " - {$error['property']}: {$error['message']}\n";
    }
}

$validator->validate($invalidData, $userSchema, Constraint::CHECK_MODE_TYPE_CAST);
if ($validator->isValid()) {
    echo "无效数据验证通过\n";
} else {
    echo "验证错误:\n";
    foreach ($validator->getErrors() as $error) {
        echo " - {$error['property']}: {$error['message']}\n";
    }
}
?>

交互式验证演示

JSON Schema

JSON 数据

最佳实践

Schema 设计原则

  • 明确性:Schema 应该清晰地描述数据的结构和约束
  • 可重用性:使用 $defs$ref 提高 Schema 的可重用性
  • 版本控制:为 Schema 添加版本信息,便于管理
  • 文档化:使用 titledescription 提供清晰的文档
  • 渐进式验证:从宽松到严格逐步加强验证规则

性能优化

  • 编译 Schema:在可能的情况下预编译 Schema 以提高性能
  • 缓存验证器:缓存编译后的验证器避免重复编译
  • 异步验证:对于大型数据,考虑使用异步验证
  • 分块验证:将大型 Schema 分解为多个小 Schema

常见陷阱

  • 循环引用:避免在 Schema 中创建循环引用
  • 过度验证:不要过度限制数据,保持适当的灵活性
  • 忽略错误处理:始终处理验证错误并提供有意义的错误信息
  • 版本混淆:明确指定 Schema 版本避免兼容性问题

工具和资源

常用验证器

语言 库名称 特点
JavaScript Ajv 性能优秀,功能完整
Python jsonschema 官方维护,功能完善
Java everit-org/json-schema 功能完整,性能良好
PHP justinrainbow/json-schema 流行度高,文档完善
Go go-jsonschema 性能优秀,类型安全

在线工具