Nestjs中ValidationPipe详解

810 阅读2分钟

在nestjs项目中,当我们的定义了DTO之后,不代表就可以自动对请求数据进行验证了,我们需要把DTO作为类型提示添加到的参数上,代码如下:

// controller 文件
export class UserController {
    @Get()
    async userList(
        @Query()
        options: QueryUserDto
    ){
        return '用户列表'
    }
}

加上了DTO之后仍然不能对数据进行校验。

image.png

发送请求之后,仍然能够正常响应数据:123

要想使他开始校验,则必须要在Query,Body等装饰器上加上ValidationPipe管道才能对请求数据进行验证 代码如下:

    @Get()
    @SerializeOptions({ groups: ['post-list'] })
    async list(
        @Query(
            new ValidationPipe({
                transform: true,
                forbidUnknownValues: true,
                validationError: { target: false },
                whitelist: true
            }),
        )
        options: QueryPostDto,
    ) {
        console.log(options)
        return '用户列表'
    }

ValidationPipe的处理步骤

  1. 先将传进来普通对象通过 class-transformer 包的 plainToClass 函数转化成 dto 类的实例.
  2. 将得到的这个 dto 实例通过 class-validator 包的 validate 函数进行验证,validate 函数同时会对 dto 实例进行相应处理(比如,设置了 whitelist, 会删除没有被 class-Validator 装饰器装饰的属性)
  3. 将这个 dto 实例再次通过 class-transformer 包的 classToPlain 函数将 dto 实例转化成普通对象
  4. controller 方法收到相应参数

具体参数(部分)的作用

可以看到这里传入了3个参数:transform,forbidUnknownValues,validationError,whitelist

  • transform 当设置为true的时候,ValidationPipe 在处理的时候就会跳过第3步。 开启transform之后,会将传入的请求数据转化为以下形式,一个DTO类的实例对象

    QueryPostDto {
      test: undefined,
      aaa: false,
      bbb: 'xxx',
      page: 1,
      limit: 10,
      id: '123'
    }
    
  • forbidUnknownValues 规定了DTO中的至少有一个属性是添加了验证规则装饰器的

  • validationError.target 指示是否应该在ValidationError中公开目标(这个是官方文档的说明)。

  • whitelist 如果设置为true,验证器将剥离已验证(返回)对象中不使用任何验证装饰器的任何属性。 比如在请求的时候我传了一个额外的aaa,处理的时候就会将aaa删除掉

    QueryPostDto {
     test: undefined,
     bbb: 'xxx',
     page: 1,
     limit: 10,
     id: '123'
    }
    

文档和源码地址

docs.nestjs.com/techniques/… [github.com/nestjs/nest…]

(github.com/nestjs/nest… "github.com/nestjs/nest…")