Nestjs 类验证器异常 - 如何为 @IsNotIn 验证器抛出元数据信息

问题描述 投票:0回答:1

我有一个 NestJs dto,看起来像这样

import { IsEmail, IsNotEmpty, IsNotIn } from 'class-validator';
import { AppService } from './app.service';
const restrictedNames = ['Name Inc', 'Acme Inc'];
class DTO {
  @IsNotEmpty()
  name: string;
  @IsEmail()
  email: string;

  @IsNotEmpty()
  @IsNotIn(restrictedNames)
  orgName: string;
}

我正在使用一个异常过滤器,它返回错误,并提供有关验证失败的内容和哪个字段的清晰详细信息。

app.useGlobalPipes(
new ValidationPipe({
  exceptionFactory: (validationErrors: ValidationError[] = []) => {
    console.log(validationErrors);
    return new BadRequestException({
      statusCode: HttpStatus.BAD_REQUEST,
      message: validationErrors.reduce((acc, error) => {
        acc[error.property] = Object.keys(error.constraints).map(
          (failed) => ({
            failedValidation: failed,
            message: error.constraints[failed],
          }),
        );
        return acc;
      }, {}),
      error: 'validation',
    });
  },
}),

);

返回类似这样的错误

{"statusCode":400,"message":{"email":[{"failedValidation":"isEmail","message":"email must be an email"}],"orgName":[{"failedValidation":"isNotIn","message":"orgName should not be one of the following values: Name Inc, Acme Inc"}]},"error":"validation"}

但是对于失败的验证(例如@NotIn),我希望错误在保留关键字方面更加具体,并希望它们作为单独的键在错误中返回,例如:

{"statusCode":400,"message":{"email":[{"failedValidation":"isEmail","message":"email must be an email"}],"orgName":[{"failedValidation":"isNotIn","message":"orgName should not be one of the following values: Name Inc, Acme Inc", "data":{"reservedKeywords":["Name Inc","Acme Inc"]}}]},"error":"validation"}

但是异常 Filter 中的此块不会返回带有装饰器元数据的约束值。

message: validationErrors.reduce((acc, error) => {
        acc[error.property] = Object.keys(error.constraints).map(
          (failed) => ({
            failedValidation: failed,
            message: error.constraints[failed],
          }),
        );
        return acc;
      }, {}),
      error: 'validation',
    });
node.js typescript nestjs class-validator
1个回答
0
投票

据我所知,不存在自动返回元数据或任何其他内容的概念。由于您将列入黑名单的值存储在变量中。您可以将其提供为

context
,它映射到特定的错误类型。

const restrictedNames = ['Name Inc', 'Acme Inc'] as const;
class DTO {
  @IsNotEmpty()
  name: string;
  @IsEmail()
  email: string;

  @IsNotEmpty()
  @IsNotIn(restrictedNames, { context: { reservedKeywords: restrictedNames } }) // here
  orgName: string;

  // You may ignore the contructor
  constructor(name: string, email: string, orgName: string) {
    this.name = name;
    this.email = email;
    this.orgName = orgName;
  }
}

现在您需要做的就是使用

error.contexts

有条件地将值包含在转换函数中
const transformedMessage = errors.reduce((acc, error) => {
  acc[error.property] = Object.keys(error.constraints).map((failed) => ({
    failedValidation: failed,
    message: error.constraints[failed],
    data: error.contexts && error.contexts[failed],
  }));
  return acc;
}, {});

如您所愿,这是输出。

{
  "email": [
    {
      "failedValidation": "isEmail",
      "message": "email must be an email"
    }
  ],
  "orgName": [
    {
      "failedValidation": "isNotIn",
      "message": "orgName should not be one of the following values: Name Inc, Acme Inc",
      "data": {
        "reservedKeywords": [
          "Name Inc",
          "Acme Inc"
        ]
      }
    }
  ]
}

PS:感谢提供转换功能。我可耻地偷了它。

© www.soinside.com 2019 - 2024. All rights reserved.