【问题标题】:validate nested objects using class-validator in nest.js controller在 nest.js 控制器中使用类验证器验证嵌套对象
【发布时间】:2019-05-08 02:21:41
【问题描述】:

我想在 nest.js 控制器中使用 class-validator 来验证 body 有效负载。我的currency.dto.ts 文件是这样的:

import {
  IsNotEmpty,
  IsString,
  ValidateNested,
  IsNumber,
  IsDefined,
} from 'class-validator';

class Data {

  @IsNotEmpty()
  @IsString()
  type: string;

  @IsNotEmpty()
  @IsNumber()
  id: number;
}

export class CurrencyDTO {
  @ValidateNested({ each: true })
  @IsDefined()
  data: Data[];
}

在我的 nest.js 控制器中,我是这样使用它的。

  @Post()
  @UseGuards(new AuthTokenGuard())
  @UsePipes(new ValidationPipe())
  addNewCurrency(@Req() req, @Body() data: CurrencyDTO) {
    console.log('data', data);
  }

我的验证管道类是这样的:

import {
  PipeTransform,
  Injectable,
  ArgumentMetadata,
  BadRequestException,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { validate, IsInstance } from 'class-validator';
import { plainToClass, Exclude } from 'class-transformer';

@Injectable()
export class ValidationPipe implements PipeTransform<any> {
  async transform(value: any, metadata: ArgumentMetadata) {
    if (value instanceof Object && this.isEmpty(value)) {
      throw new HttpException(
        `Validation failed: No Body provided`,
        HttpStatus.BAD_REQUEST,
      );
    }
    const { metatype } = metadata;
    if (!metatype || !this.toValidate(metatype)) {
      return value;
    }
    const object = plainToClass(metatype, value);
    const errorsList = await validate(object);
    if (errorsList.length > 0) {
      const errors = [];
      for (const error of errorsList) {
        const errorsObject = error.constraints;
        const { isNotEmpty } = errorsObject;
        if (isNotEmpty) {
          const parameter = isNotEmpty.split(' ')[0];
          errors.push({
            title: `The ${parameter} parameter is required.`,
            parameter: `${parameter}`,
          });
        }
      }
      if (errors.length > 0) {
        throw new HttpException({ errors }, HttpStatus.BAD_REQUEST);
      }
    }
    return value;
  }

  private toValidate(metatype): boolean {
    const types = [String, Boolean, Number, Array, Object];
    return !types.find(type => metatype === type);
  }
  private isEmpty(value: any) {
    if (Object.keys(value).length > 0) {
      return false;
    }
    return true;
  }
}

此验证管道适用于除嵌套对象之外的所有对象。知道我在这里做错了什么吗? 我的身体载荷是这样的:

{
"data": [{
    "id": 1,
    "type": "a"
}]
}

【问题讨论】:

    标签: node.js typescript validation nestjs class-validator


    【解决方案1】:

    尝试使用@Type 指定嵌套类型:

    import { Type } from 'class-transformer';
    
    export class CurrencyDTO {
      @ValidateNested({ each: true })
      @Type(() => Data)
      data: Data[];
    }
    

    对于要验证的嵌套类型,它必须是类的实例,而不仅仅是普通数据对象。使用@Type 装饰器,当在VaildationPipe 中调用plainToClass 时,您告诉class-transformer 为给定属性实例化一个类。

    如果您使用的是内置的ValidationPipe,请确保您已设置选项transform: true

    【讨论】:

    • 出于任何原因,此解决方案对我不起作用。我按照你说的做了,但是没有用。
    • 我已经尝试过了,它对我有用。 :-/ 没有更具体的信息,我帮不了你。也许打开一个新问题并添加您的代码?!我去看看。
    • 我刚开了一个新帖子,如果你能看一下,我将不胜感激。
    • 我会补充。该类验证器不需要此 \@Type 注释。这就是nestjs 的工作方式。它总是在你的 DTO 上使用 class-transformer,而 class-transformer 需要 \@Type 注释。
    • @LeonardoEmilioDominguez 尝试将两个类放在同一个文件中,并确保嵌套类首先出现(应该在顶部),顺序很重要。如您所见,数据出现在问题中的 DataDTO 之前。
    【解决方案2】:

    至少在我的情况下,接受的答案需要更多信息。照原样,如果请求中不存在密钥 data,验证将不会运行。要获得完整的验证,请尝试:

    @IsDefined()
    @IsNotEmptyObject()
    @ValidateNested()
    @Type(() => CreateOrganizationDto)
    @ApiProperty()
    organization: CreateOrganizationDto;
    

    【讨论】:

      猜你喜欢
      • 2021-04-22
      • 2019-05-16
      • 2012-09-22
      • 2020-06-04
      • 2020-12-02
      • 1970-01-01
      • 2022-01-10
      • 2022-01-24
      相关资源
      最近更新 更多