Node.js中如何使用Joi验证日期字符串格式及大小关系
Joi 实现日期字段双规则校验方案
直接修改原有验证规则即可,核心改动分为单字段格式校验、跨字段大小比较两部分,完全兼容原有convert: false、abortEarly: false、允许空值/可选的配置。
规则修改说明
- 单字段格式校验:将原有的
Joi.string()替换为Joi.date().format('YYYY-MM-DD'),在convert:false配置下,该规则只会校验字符串是否严格匹配YYYY-MM-DD日期格式,不会将入参转换为Date对象,校验通过后字段依然保留原字符串类型。 - 跨字段大小校验:通过
Joi.ref()引用endDate字段,配合.less()规则实现startDate早于endDate的校验,同时通过条件判断跳过空值场景的比较,避免空值触发校验报错。 - 可选增强配置:可增加
with规则,实现“传了开始日期就必须传结束日期,反之亦然”的逻辑,避免单传一个日期参数的无效请求。
完整修改后的中间件代码
export const validateMiddleware = async (req, res, next) => { const validateExpression = Joi.object() .keys({ 'startDate': Joi.date() .format('YYYY-MM-DD') .optional() .allow('') // 当endDate为非空有效值时,校验startDate小于endDate .when('endDate', { is: Joi.date().format('YYYY-MM-DD').required(), then: Joi.date().less(Joi.ref('endDate')) .messages({ 'date.less': 'startDate 必须早于 endDate' }) }), 'endDate': Joi.date() .format('YYYY-MM-DD') .optional() .allow('') }) // 可选规则:两个日期字段只要传了其中一个,另一个必须传,按需开启即可 // .with('startDate', 'endDate') // .with('endDate', 'startDate'); const { error } = validateExpression.validate(req.query, { 'convert': false, 'abortEarly': false }); if (error) { // 原有错误返回逻辑不变,错误详情会包含格式错误、日期大小错误所有信息 return res.status(400).json({ code: 400, message: '参数校验失败', errors: error.details.map(item => item.message) }) } else { next(); } };
校验效果说明
- 传入空字符串、不传startDate/endDate:校验通过
- 传入非YYYY-MM-DD格式的字符串(比如
2024/01/01、2024-13-01、abc):触发格式错误 - startDate大于等于endDate(比如startDate为
2024-05-01,endDate为2024-04-01):触发日期大小校验错误 - 所有错误会因为
abortEarly: false配置一次性全部返回,不会只返回第一个错误
内容的提问来源于stack exchange,提问作者SPARSH KUMAR
相关产品推荐
相关产品推荐

