当我需要验证数组的内容时,NestJS 中的 ValidationPipe 出现问题

Problems with ValidationPipe in NestJS when I need to validate the contents of an array

我的客户端用户可以输入零个或多个地址。我的问题是,如果他输入一个地址,有些字段需要是强制性的。

user.controller.ts

@Post()
@UsePipes(ValidationPipe)
async createUser(
    @Body() createUser: CreateUserDto,
) {
    return await this.service.saveUserAndAddress(createUser);
}

创建-user.dto.ts

export class CreateUserDto {
    @IsNotEmpty({ message: 'ERROR_REQUIRED_FULL_NAME' })
    fullName?: string;

    @IsNotEmpty({ message: 'ERROR_REQUIRED_PASSWORD' })
    password?: string;

    @IsNotEmpty({ message: 'ERROR_REQUIRED_EMAIL' })
    @IsEmail({}, { message: 'ERROR_INVALID_EMAIL' })
    email?: string;

    ...

    addresses?: CreateUserAddressDto[];
}

创建用户-address.dto.ts

export class CreateUserAddressDto {
    ...

    @IsNotEmpty()
    street: string;

    ...
}

CreateUserDto 数据被正确验证并生成 InternalServerErrorResponse,但是当我的数组中有某些项目时 CreateUserAddressDto 数据未被验证。知道如何进行此验证吗?

您正在尝试做的是 - 基本上向开箱即用的原始验证器添加逻辑 nest - 又名 - 定义自定义验证器。

这可以通过使用 class 验证器提供的两个 classes ValidatorConstraintValidatorConstraintInterface 来完成。

为了对此进行排序,将传入的输入/俱乐部任何您想要立即验证的数据转换为对象 - 使用 nestjs 中的管道或将其作为对象发送到 API 调用本身,然后在其上附加一个验证器。

定义自定义验证器:

import { ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator';


/**
 * declare your custom validator here
 */
@ValidatorConstraint({ name: 'MyValidator', async: false })
export class MyValidator implements ValidatorConstraintInterface {
  
   /** return true when tests pass **/
   validate(incomingObject: myIncomingDataInterface) {
    try {
     // your logic regarding what all is required in the object
     const output = someLogic(incomingObject);
     return output;
    } catch (e) {
      return false;
    }
  }

  defaultMessage() {
    return 'Address update needs ... xyz';
  }
}

一旦你定义了它,请根据你的项目结构将它安全地保存在某个地方。现在你只需要在你想进行验证时调用它。

在数据传输对象中,

// import the validator
import { Validate } from 'class-validator';
import { MyValidator } from './../some/safe/place'

export class SomeDto{
    @ApiProperty({...})
    @Validate(MyValidator)
    thisBecomesIncomingObjectInFunction: string;
}

就这么简单。

Nest fw 使用 class-transformer 将 json 转换为 class 对象。如果它不是原始值,则必须为子属性设置正确的类型。而你的属性是一个数组,你必须配置告诉 class-validator 它是一个数组,并在每个项目上进行验证。

让我们更新一下CreateUserDto

import { Type } from 'class-transformer';
import { ..., ValidateNested } from 'class-validator';

export class CreateUserAddressDto {
    ...


    @ValidateNested({ each: true })
    @Type(() => CreateUserAddressDto)
    addresses?: CreateUserAddressDto[];

    ...
}