我使用带有类验证器的 NestJS 来验证传入的请求。在我的 SignUpDto 类中,我应用了 IsNotEmpty、IsString 和 IsEmail 等验证装饰器来验证电子邮件和密码字段。我希望验证错误以与应用装饰器相同的顺序抛出,但仅抛出一个错误(如果)。
为了实现这一目标,我使用 exceptionFactory 抛出 app.useGlobalPipes 配置中唯一的一个错误。但是,错误不会按预期顺序抛出(因为我只返回索引 0 处的错误)
我有什么方法可以解决这个问题,这样我就可以按相同的顺序显示错误,但一次只显示一个错误?
// SignUpDto.ts
import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator';
export class SignUpDto {
@IsNotEmpty({ message: 'Email should not be empty' })
@IsString({ message: 'Invalid email format' })
@IsEmail({}, { message: 'Invalid email format' })
email: string;
@IsNotEmpty({ message: 'Password should not be empty' })
@IsString({ message: 'Invalid password format' })
@MinLength(8, { message: 'Password must be at least 8 characters long' })
password: string;
}
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import {
BadRequestException,
HttpException,
HttpStatus,
ValidationPipe,
} from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors({
origin: true,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
credentials: true,
});
app.useGlobalPipes(
new ValidationPipe({
stopAtFirstError: true,
whitelist: true,
exceptionFactory: (errors) => {
const messages = errors[0].constraints;
const message = Object.values(messages)[0];
const response = { message, statusCode: HttpStatus.BAD_REQUEST };
throw new HttpException(response, HttpStatus.BAD_REQUEST);
},
}),
);
await app.listen(5001);
}
bootstrap();
您正在使用 TypeScript 装饰器(从
class-validator
导入的装饰器)来添加 DTO 的验证。
TypeScript 装饰器是自下而上执行的。您可以参考https://www.typescriptlang.org/docs/handbook/decorators.html#decorator-composition了解更多详情。
这意味着在您给定的 DTO 中:
export class SignUpDto {
@IsNotEmpty({ message: 'Email should not be empty' })
@IsString({ message: 'Invalid email format' })
@IsEmail({}, { message: 'Invalid email format' })
email: string;
}
你的装饰器的执行顺序将是:
IsEmail
IsString
IsNotEmpty
我假设你想要另一种方式。这意味着,您需要将装饰器顺序调整为:
export class SignUpDto {
@IsEmail({}, { message: 'Invalid email format' })
@IsString({ message: 'Invalid email format' })
@IsNotEmpty({ message: 'Email should not be empty' })
email: string;
}
这应该可以为您解决订单问题。
对于仅返回 1 个错误的第二个查询,您的方法看起来不错。同时使用
stopAtFirstError
和 executionFactory
将是最简单的方法。