理解 JSON Schema:轻松验证
掌握 JSON Schema 进行数据验证。学习模式语法、验证技术以及在不同编程语言中的实现。
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# 理解 JSON Schema:轻松验证
JSON Schema 是用于验证和描述 JSON 文档的词汇表。它定义了 JSON 数据的结构、约束和验证规则,确保数据质量和一致性。
什么是 JSON Schema?
JSON Schema 是一个强大的工具,用于:
- ✅ 验证数据结构:确保 JSON 符合期望的格式
- ✅ 文档化 API:清晰描述数据要求
- ✅ 生成代码:自动创建类型定义
- ✅ 测试:验证测试数据
- ✅ 配置验证:检查配置文件
基本 Schema 示例
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/user.schema.json",
"title": "用户",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "用户姓名"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150,
"description": "用户年龄"
},
"email": {
"type": "string",
"format": "email",
"description": "电子邮件地址"
}
},
"required": ["name", "email"]
}
验证此数据:
{
"name": "张三",
"age": 30,
"email": "zhangsan@example.com"
}
✅ 有效
{
"name": "李四",
"email": "invalid-email"
}
❌ 无效(电子邮件格式错误)
Schema 关键字
类型关键字
type
定义值的数据类型:
{
"type": "string" // 字符串
}
{
"type": "number" // 数字
}
{
"type": "integer" // 整数
}
{
"type": "boolean" // 布尔值
}
{
"type": "object" // 对象
}
{
"type": "array" // 数组
}
{
"type": "null" // 空值
}
多类型
{
"type": ["string", "null"]
}
字符串验证
{
"type": "string",
"minLength": 3,
"maxLength": 50,
"pattern": "^[A-Za-z]+$"
}
格式:
{
"type": "string",
"format": "email" // 电子邮件
}
{
"type": "string",
"format": "uri" // URI
}
{
"type": "string",
"format": "date" // 日期 (YYYY-MM-DD)
}
{
"type": "string",
"format": "time" // 时间
}
{
"type": "string",
"format": "date-time" // 日期时间
}
{
"type": "string",
"format": "ipv4" // IPv4 地址
}
{
"type": "string",
"format": "ipv6" // IPv6 地址
}
数字验证
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": 0,
"exclusiveMaximum": 100,
"multipleOf": 5
}
示例:
{
"type": "integer",
"minimum": 18,
"maximum": 120,
"description": "年龄必须在 18 到 120 之间"
}
对象验证
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
}
},
"required": ["name"],
"additionalProperties": false,
"minProperties": 1,
"maxProperties": 10
}
数组验证
{
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
不同项类型:
{
"type": "array",
"items": [
{"type": "string"},
{"type": "number"},
{"type": "boolean"}
]
}
实际示例
用户注册 Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "用户注册",
"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,
"description": "至少 8 个字符的密码"
},
"age": {
"type": "integer",
"minimum": 13,
"description": "必须至少 13 岁"
},
"terms": {
"type": "boolean",
"const": true,
"description": "必须接受条款"
}
},
"required": ["username", "email", "password", "terms"]
}
产品 Schema
{
"title": "产品",
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^PROD-[0-9]+$"
},
"name": {
"type": "string",
"minLength": 1
},
"price": {
"type": "number",
"minimum": 0,
"multipleOf": 0.01
},
"inStock": {
"type": "boolean"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
},
"specifications": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"required": ["id", "name", "price"]
}
JavaScript 中的验证
使用 Ajv
安装:npm install ajv
基本用法:
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv);
const schema = {
type: 'object',
properties: {
name: { type: 'string', minLength: 2 },
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0 }
},
required: ['name', 'email']
};
const validate = ajv.compile(schema);
// 测试数据
const data1 = {
name: "张三",
email: "zhangsan@example.com",
age: 30
};
if (validate(data1)) {
console.log('数据有效!');
} else {
console.log('验证失败:', validate.errors);
}
// 无效数据
const data2 = {
name: "李", // 太短
email: "invalid-email" // 无效格式
};
if (!validate(data2)) {
console.log('错误:', validate.errors);
// 错误: [
// {
// instancePath: '/name',
// message: 'must NOT have fewer than 2 characters'
// },
// {
// instancePath: '/email',
// message: 'must match format "email"'
// }
// ]
}
自定义错误消息
import Ajv from 'ajv';
import ajvErrors from 'ajv-errors';
const ajv = new Ajv({ allErrors: true });
ajvErrors(ajv);
const schema = {
type: 'object',
properties: {
age: {
type: 'integer',
minimum: 18,
errorMessage: '年龄必须至少为 18 岁'
}
},
required: ['age'],
errorMessage: {
required: '缺少必需字段'
}
};
const validate = ajv.compile(schema);
Python 中的验证
使用 jsonschema
安装:pip install jsonschema
基本用法:
from jsonschema import validate, ValidationError
import json
schema = {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 2
},
"email": {
"type": "string",
"format": "email"
},
"age": {
"type": "integer",
"minimum": 0
}
},
"required": ["name", "email"]
}
# 有效数据
data = {
"name": "张三",
"email": "zhangsan@example.com",
"age": 30
}
try:
validate(instance=data, schema=schema)
print("数据有效!")
except ValidationError as e:
print(f"验证失败:{e.message}")
print(f"路径:{list(e.path)}")
使用 Pydantic
from pydantic import BaseModel, EmailStr, Field, validator
from typing import Optional
class User(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
email: EmailStr
age: int = Field(..., ge=0, le=150)
phone: Optional[str] = None
@validator('name')
def name_must_not_contain_numbers(cls, v):
if any(char.isdigit() for char in v):
raise ValueError('姓名不能包含数字')
return v
# 使用
try:
user = User(
name="张三",
email="zhangsan@example.com",
age=30
)
print(f"用户创建成功:{user.name}")
except ValueError as e:
print(f"验证错误:{e}")
高级功能
$ref - Schema 引用
重用 schema 定义:
{
"$defs": {
"address": {
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"},
"zipCode": {"type": "string", "pattern": "^[0-9]{6}$"}
},
"required": ["street", "city"]
}
},
"type": "object",
"properties": {
"homeAddress": {
"$ref": "#/$defs/address"
},
"workAddress": {
"$ref": "#/$defs/address"
}
}
}
allOf - 所有条件
{
"allOf": [
{"type": "object", "properties": {"name": {"type": "string"}}},
{"properties": {"age": {"type": "integer"}}}
]
}
anyOf - 任一条件
{
"anyOf": [
{"type": "string"},
{"type": "number"}
]
}
oneOf - 恰好一个条件
{
"oneOf": [
{"properties": {"type": {"const": "person"}}, "required": ["name"]},
{"properties": {"type": {"const": "company"}}, "required": ["companyName"]}
]
}
if/then/else - 条件验证
{
"type": "object",
"properties": {
"country": {"type": "string"}
},
"if": {
"properties": {"country": {"const": "中国"}}
},
"then": {
"properties": {
"postalCode": {"pattern": "^[0-9]{6}$"}
}
},
"else": {
"properties": {
"postalCode": {"type": "string"}
}
}
}
Schema 生成
从 JSON 生成
import json
from genson import SchemaBuilder
# 样本数据
data = [
{"name": "张三", "age": 30, "email": "zhangsan@example.com"},
{"name": "李四", "age": 25, "email": "lisi@example.com"}
]
# 生成 schema
builder = SchemaBuilder()
for item in data:
builder.add_object(item)
schema = builder.to_schema()
print(json.dumps(schema, indent=2, ensure_ascii=False))
从 TypeScript 接口
import { compile } from 'json-schema-to-typescript';
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'integer' }
}
};
compile(schema, 'User').then(ts => console.log(ts));
// 输出:
// export interface User {
// name?: string;
// age?: number;
// }
最佳实践
1. 使用描述性标题和描述
{
"title": "用户资料",
"description": "用于用户配置文件验证的完整 schema",
"properties": {
"email": {
"type": "string",
"format": "email",
"description": "用户的主要电子邮件地址"
}
}
}
2. 提供示例
{
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["active", "inactive", "pending"],
"examples": ["active"]
}
}
}
3. 使用 $id 和 $schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/user.json"
}
4. 重用定义
{
"$defs": {
"positiveInteger": {
"type": "integer",
"minimum": 1
}
},
"properties": {
"age": { "$ref": "#/$defs/positiveInteger" },
"count": { "$ref": "#/$defs/positiveInteger" }
}
}
5. 验证敏感操作
// API 端点
app.post('/api/users', async (req, res) => {
const valid = validate(req.body);
if (!valid) {
return res.status(400).json({
error: '验证失败',
details: validate.errors
});
}
// 处理有效数据
const user = await createUser(req.body);
res.status(201).json(user);
});
工具和资源
在线验证器
- JSON Schema Validator
- JSONLint (with schema support)
库
JavaScript:- Ajv(最快)
- Joi
- Yup
- jsonschema
- Pydantic
- marshmallow
- Java: json-schema-validator
- Go: gojsonschema
- Ruby: json-schema
IDE 支持
- VS Code:内置 JSON Schema 支持
- IntelliJ:JSON Schema 插件
- Sublime Text:LSP-json
结论
JSON Schema 是确保数据质量和一致性的强大工具。通过掌握 schema 定义和验证,您可以:
- ✅ 防止无效数据进入系统
- ✅ 清晰记录 API 合同
- ✅ 自动生成类型定义
- ✅ 提高代码质量和可维护性
- ✅ 减少运行时错误
关键要点
$ref 重用定义开始在您的项目中使用 JSON Schema,享受类型安全和数据验证的好处!