Ajv 实战:Node.js JSON Schema 校验指南
Ajv 是 Node.js 生态的 JSON Schema 校验器,把 Schema 编译成可复用的校验函数;实际性能取决于 Schema、数据和配置。本文讲解 Ajv 的安装、Schema 编写、格式校验、自定义规则与错误信息处理。
Ajv 把 JSON Schema 编译成高度优化的 JavaScript 函数来校验数据,适合需要复用标准 Schema 的 Node.js 项目。基本用法三步:new Ajv() 创建实例、ajv.compile(schema) 编译 Schema、调用编译出的函数校验数据——返回 false 时从 validate.errors 读取逐条错误明细。
为什么是 Ajv
JSON Schema 是描述数据结构的标准,而 Ajv 是它在 Node.js 的事实标准实现:Fastify 等框架内建用它做请求校验。性能秘诀在于编译而非解释——Schema 只编译一次,之后每次校验就是跑一个为这份 Schema 量身定制的函数。
安装与快速开始
npm install ajv ajv-formats
const Ajv = require('ajv');
const addFormats = require('ajv-formats');
const ajv = new Ajv({ allErrors: true });
addFormats(ajv); // 启用 email、uri、date-time 等格式校验
const schema = {
type: 'object',
properties: {
name: { type: 'string', minLength: 1 },
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0 }
},
required: ['name', 'email'],
additionalProperties: false
};
const validate = ajv.compile(schema);
const ok = validate({ name: '观测云', email: 'a@b.com' });
if (!ok) console.log(validate.errors);
allErrors: true 让校验跑完全程返回所有错误(默认遇到第一个就停),对用户表单更友好。additionalProperties: false 禁止 Schema 未声明的字段,是防止脏数据渗入的关键开关。
常用规则速查
- 字符串:
minLength/maxLength/pattern(正则)/format(email、uri、date-time、uuid); - 数字:
minimum/maximum/exclusiveMinimum/multipleOf; - 数组:
items(元素 Schema)/minItems/uniqueItems; - 枚举与常量:
enum: ['a', 'b']、const: 'v1'; - 条件组合:
anyOf(任一满足)/oneOf(恰好一个)/allOf(全部满足)/if-then-else条件分支。
自定义校验规则
内置规则不够用时,用 addKeyword 扩展:
ajv.addKeyword({
keyword: 'isPhone',
type: 'string',
schemaType: 'boolean',
validate: (schemaVal, data) => !schemaVal || /^1\d{10}$/.test(data),
errors: false
});
const schema = { type: 'string', isPhone: true };
这里仅检查以 1 开头的 11 位数字外形,不验证号码分配或可用性。
复杂跨字段校验(如"结束时间必须大于开始时间")也可以直接用代码函数实现,比纯 Schema 表达更直观。
错误信息的可读化
validate.errors 是结构化数组(instancePath + message),直接抛给用户太生硬。生产实践:写一个格式化函数把 errors 映射成 { 字段: 中文提示 } 结构,或引入 ajv-errors 在 Schema 里直接声明自定义错误消息。
常见问题(FAQ)
Q:Ajv 和 Zod/Joi 怎么选?
Ajv 是"JSON Schema 标准的实现",Schema 可跨语言共享、与 OpenAPI 的兼容性需按其版本和 Schema 方言核对;Zod 是 TypeScript 优先的体验派(类型自动推导);Joi 语法链式友好。Fastify 生态选 Ajv,TS 全栈选 Zod,详见本系列 Joi、Zod 对比篇。
Q:为什么 format: 'email' 不生效?
Ajv 从 v7 起把 format 拆成独立包:必须 npm i ajv-formats 并 addFormats(ajv),默认遇到未知 format 会在编译 Schema 时抛错;strict: false 不会补上实际格式校验。
Q:Strict 模式报错怎么关闭?
new Ajv({ strict: false }),但建议保持开启并修正 Schema——strict 拦下的多是 Schema 写法的真实问题(如未声明的 type),关掉等于蒙眼开车。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。