JSON Schema
什么是 JSON Schema?
JSON Schema 是一种基于 JSON 的格式,用于描述 JSON 数据的结构。它允许你验证 JSON 文档、提供交互式文档,并控制客户端和服务器之间的数据交互。
简单示例
{
"$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";
}
}
?>
最佳实践
Schema 设计原则
- 明确性:Schema 应该清晰地描述数据的结构和约束
- 可重用性:使用
$defs 和 $ref 提高 Schema 的可重用性
- 版本控制:为 Schema 添加版本信息,便于管理
- 文档化:使用
title 和 description 提供清晰的文档
- 渐进式验证:从宽松到严格逐步加强验证规则
性能优化
- 编译 Schema:在可能的情况下预编译 Schema 以提高性能
- 缓存验证器:缓存编译后的验证器避免重复编译
- 异步验证:对于大型数据,考虑使用异步验证
- 分块验证:将大型 Schema 分解为多个小 Schema
常见陷阱
- 循环引用:避免在 Schema 中创建循环引用
- 过度验证:不要过度限制数据,保持适当的灵活性
- 忽略错误处理:始终处理验证错误并提供有意义的错误信息
- 版本混淆:明确指定 Schema 版本避免兼容性问题
工具和资源
常用验证器
| 语言 |
库名称 |
特点 |
| JavaScript |
Ajv |
性能优秀,功能完整 |
| Python |
jsonschema |
官方维护,功能完善 |
| Java |
everit-org/json-schema |
功能完整,性能良好 |
| PHP |
justinrainbow/json-schema |
流行度高,文档完善 |
| Go |
go-jsonschema |
性能优秀,类型安全 |
在线工具