class-validator的IsDateString校验失败:值为ISO字符串却报错?
解决class-validator IsDateString校验MongoDB Date字段报错的问题
我来帮你分析一下这个问题的根源,以及对应的解决办法:
问题原因
你遇到的核心矛盾是装饰器的校验目标和字段类型不匹配:
@IsDateString装饰器的作用是校验字符串是否符合ISO 8601日期格式;- 但你的
createdAt字段类型是Date,当你从MongoDB取出文档转成JSON后,createdAt是ISO格式的字符串,再通过plainToClass转换时,class-transformer会自动把这个字符串转换成Date对象; - 此时
@IsDateString校验的是Date对象而非字符串,自然会触发"must be a ISOString"的错误。
快速解决方案
根据你的业务需求,有两种合理的修复方式:
方案一:改用@IsDate装饰器(推荐)
既然你的字段类型是Date,直接使用专门校验Date对象的@IsDate装饰器即可:
import { IsDate, IsDefined } from 'class-validator'; import { prop } from '@typegoose/typegoose'; class FinishedOrder { @prop({ default: new Date(Date.now()) }) @IsDefined() @IsDate() // 替换原有的@IsDateString createdAt: Date; }
这样校验逻辑会正确识别Date对象,不会再报错。
方案二:保留@IsDateString,调整字段类型为字符串
如果你确实需要校验ISO格式的字符串,可以把字段类型改为string,同时调整Mongoose的存储逻辑:
import { IsDateString, IsDefined } from 'class-validator'; import { prop } from '@typegoose/typegoose'; class FinishedOrder { // 默认值改为ISO字符串,存储时也存字符串类型 @prop({ default: () => new Date().toISOString() }) @IsDefined() @IsDateString() createdAt: string; }
同时在plainToClass转换时,可以关闭隐式转换避免自动转成Date对象:
let finalOrder = plainToClass(FinishedOrder, orderData, { enableImplicitConversion: false, });
验证修复
修改后重新执行你的校验逻辑:
const order = await this.order.findOne({ _id: body._id, clientId: user.clientId }); let orderData = order.toJSON(); let finalOrder = plainToClass(FinishedOrder, orderData); let validation = await validateOrReject(finalOrder);
此时校验应该能顺利通过。
内容的提问来源于stack exchange,提问作者SebastianG
相关产品推荐
相关产品推荐

