通过 @IsInt() 验证 application/x-www-form-urlencoded 请求类型

Pav*_*kov 3 node.js class-validator nestjs class-transformer

当我浏览Pipes文档时,我注意到我无法正确@IsInt()验证application/x-www-form-urlencoded请求,导致我通过的所有值都作为字符串值接收。

我的请求数据如下所示 在此处输入图片说明

我的 DTO 看起来像

import { IsString, IsInt } from 'class-validator';

export class CreateCatDto {
    @IsString()
    readonly name: string;

    @IsInt()
    readonly age: number;

    @IsString()
    readonly breed: string;
}
Run Code Online (Sandbox Code Playgroud)

验证管道包含下一个代码

import { PipeTransform, Pipe, ArgumentMetadata, BadRequestException } from '@nestjs/common';
import { validate } from 'class-validator';
import { plainToClass } from 'class-transformer';

@Pipe()
export class ValidationPipe implements PipeTransform<any> {
    async transform(value, metadata: ArgumentMetadata) {
        const { metatype } = metadata;
        if (!metatype || !this.toValidate(metatype)) {
            return value;
        }
        const object = plainToClass(metatype, value);
        const errors = await validate(object);
        if (errors.length > 0) {
            throw new BadRequestException('Validation failed');
        }
        return value;
    }

    private toValidate(metatype): boolean {
        const types = [String, Boolean, Number, Array, Object];
        return !types.find((type) => metatype === type);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我调试这个管道时,我注意到了这个状态 在此处输入图片说明 在哪里:

  • value - 请求正文值
  • 对象- 通过类转换器转换
  • 错误- 错误对象

正如你所看到的,错误告诉我们年龄必须是一个整数

我怎样才能通过@IsInt()审定申请/的X WWW的形式,进行了urlencoded的要求吗?

库版本:

  • @nestjs/common@4.6.4
  • 类变压器@0.1.8
  • 类验证器@0.8.1

PS:我还创建了一个存储库,您可以在其中运行应用程序来测试错误。必需的分支how-to-pass-int-validation

UPD:在对接受的答案进行更改后,我遇到了将错误解析的数据放入存储的问题。录制的例子

是否有可能得到很好的解析,createCatDto或者我需要做什么才能用正确的类型结构保存它?

Cha*_*ito 5

application/x-www-form-urlencoded请求中的所有值始终是字符串。

因此,您可以执行以下操作:

import { Transform } from 'class-transformer';
import { IsString, IsInt } from 'class-validator';

export class CreateCatDto {
  @IsString()
  readonly name: string;

  @Transform(value => Number.isNan(+value) ? 0 : +value) // this field will be parsed to integer when `plainToClass gets called`
  @IsInt()
  readonly age: number;

  @IsString()
  readonly breed: string;
}
Run Code Online (Sandbox Code Playgroud)

  • 只有一个问题:`Number.isNan()` 不存在。我们需要使用 `isNaN()` 代替它。 (2认同)

Rtx*_*txx 5

添加 @Type(() => Number) 为我解决了这个问题。

import { Type } from 'class-transformer';
import { IsInt, IsNotEmpty } from 'class-validator';

@IsNotEmpty({ message: '' })
@Type(() => Number)
@IsInt({ message: '' })
project: number;
Run Code Online (Sandbox Code Playgroud)