如何用Zod实现Joi中的userId必填及Body至少一个字段校验?
用Zod实现与Joi相同的参数校验逻辑
需求说明
请求参数params必须包含userId字段(需通过自定义ObjectId格式校验);请求体body至少包含name、email、password中的一个字段。
原Joi实现代码
{ params: Joi.object().keys({ userId: Joi.required().custom(objectId), }), body: Joi.object() .keys({ name: Joi.string(), email: Joi.string().email(), password: Joi.string().custom(password), }) .min(1), };
Zod实现方案
首先确保已安装Zod:
npm install zod
1. 定义自定义校验规则
Zod通过refine方法实现自定义校验逻辑,对应Joi的custom方法:
import { z } from "zod"; // 自定义ObjectId校验(匹配MongoDB ObjectId格式) const objectIdSchema = z.string().refine( (value) => /^[0-9a-fA-F]{24}$/.test(value), { message: "userId必须是有效的ObjectId格式" } ); // 自定义密码校验(示例:至少8位,包含大写字母和数字,可根据实际需求调整) const passwordSchema = z.string().refine( (value) => value.length >= 8 && /[A-Z]/.test(value) && /[0-9]/.test(value), { message: "密码长度至少8位,需包含大写字母和数字" } );
2. 定义Params校验Schema
对应Joi中params的必填userId规则:
const paramsSchema = z.object({ userId: objectIdSchema // Zod对象字段默认必填,对应Joi的required() });
3. 定义Body校验Schema
通过partial()让字段变为可选,再用refine确保至少有一个指定字段存在,对应Joi的.min(1):
const bodySchema = z.object({ name: z.string(), email: z.string().email(), // Zod内置邮箱校验,对应Joi的.email() password: passwordSchema }) .partial() // 将所有字段设为可选 .refine( (data) => Object.keys(data).length > 0, { message: "请求体必须包含name、email、password中的至少一个字段" } );
4. 组合完整的请求校验Schema
const requestSchema = z.object({ params: paramsSchema, body: bodySchema });
使用方式
校验请求数据时,直接调用parse或safeParse方法:
// 示例:校验请求对象 const requestData = { params: { userId: "60d21b4667d0d8992e610c85" }, body: { email: "user@example.com" } }; // 严格校验(不符合则抛出错误) requestSchema.parse(requestData); // 安全校验(返回结果对象,包含success和data/error) const result = requestSchema.safeParse(requestData); if (!result.success) { console.error(result.error.issues); }
内容的提问来源于stack exchange,提问作者Deepak Kumar
相关产品推荐
相关产品推荐

