Node.js 中使用 Joi 进行数据验证
在现代基于 Node.js 的 Web 应用程序中,数据验证是处理请求的关键阶段。数据错误可能导致漏洞、运行异常或服务器崩溃。用于此任务的最强大且最流行的库之一是 Joi(发音为“乔伊”)。它允许您描述数据模式并检查它们是否符合指定规则。
什么是 Joi?
Joi 是一个用于描述模式并验证 JavaScript 对象的库。它在 Node.js 生态系统中特别流行,通常与 Express、Hapi 或 Fastify 一起使用。Joi 提供了一个简单且富有表现力的 API,用于指定类型、必填字段、范围、正则表达式和自定义检查。
安装
通过 npm 安装 Joi:
npm install joi基本示例
创建一个用于验证用户数据的模式:
const Joi = require('joi');
const schema = Joi.object({ username: Joi.string() .alphanum() .min(3) .max(30) .required(), password: Joi.string() .pattern(new RegExp('^[a-zA-Z0-9]{3,30}$')), email: Joi.string() .email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } })});
const data = { username: 'user123', password: 'pass123', email: 'user@example.com'};
const { error, value } = schema.validate(data);
if (error) { console.log('验证错误:', error.details);} else { console.log('数据有效:', value);}主要方法和规则
Joi 支持多种类型和修饰符:
- 数据类型:
Joi.string(),Joi.number(),Joi.boolean(),Joi.date(),Joi.array(),Joi.object()。 - 必填项:
.required()— 字段为必填。 - 限制:
.min(),.max(),.length()— 用于字符串和数组。 - 正则表达式:
.pattern(regex)— 根据模式检查。 - Email 和 URL:
.email(),.uri()— 内置验证器。 - 自定义消息:
.messages()— 替换默认错误。
验证嵌套对象和数组
Joi 能很好地处理复杂结构:
const addressSchema = Joi.object({ street: Joi.string().required(), city: Joi.string().required(), zip: Joi.string().pattern(/^\\d{5}$/)});
const userSchema = Joi.object({ name: Joi.string().required(), age: Joi.number().integer().min(18).max(120), addresses: Joi.array().items(addressSchema).min(1)});
const userData = { name: '安娜', age: 25, addresses: [ { street: '涅瓦大街', city: '圣彼得堡', zip: '191011' } ]};
const result = userSchema.validate(userData);console.log(result.error ? result.error.details : 'OK');错误处理
验证出错时,Joi 返回一个 error.details 对象 — 一个包含每个错误详细描述的数组:
if (result.error) { result.error.details.forEach(detail => { console.log(`字段: ${detail.path.join('.')}, 消息: ${detail.message}`); });}与 Express 一起使用
Joi 常用于中间件中检查请求:
const express = require('express');const Joi = require('joi');const app = express();
app.use(express.json());
const validateUser = (req, res, next) => { const schema = Joi.object({ name: Joi.string().required(), email: Joi.string().email().required() }); const { e