一、局部验证的方式
-
1、安装包
npm i --save class-validator class-transformer
-
2、比如在
cat
的目录下创建一个dto
的文件夹,创建一个create.cat.dto.ts
的文件import { IsString, IsInt, MinLength, MaxLength } from 'class-validator'; export class CreateCatDto { @IsString({ message: '必须的字符类型' }) @MinLength(2, { message: '长度不能小于2', }) @MaxLength(10, { message: '长度不能超过10', }) readonly name: string; @IsInt({ message: '必须的整数' }) readonly age: number; }
-
3、在
cat.controller.ts
中使用提交过来的数据约束@Controller('cat') export class CatController { constructor(private readonly catService: CatService) {} @Post() @HttpCode(HttpStatus.CREATED) async create(@Body(new ValidationPipe()) createCatDto: CreateCatDto) { Logger.log('-----------创建猫 start--------------'); Logger.log(createCatDto); Logger.log('-----------创建猫 end--------------'); return '创建猫'; } ... }
二、全局使用管道校验(前提是先安装包)
-
1、在根目录下的
main.ts
文件中import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { Logger, ValidationPipe } from '@nestjs/common'; import * as helmet from 'helmet'; async function bootstrap() { const app = await NestFactory.create(AppModule, { cors: true, // 设置跨站访问 logger: false, }); // 使用跨站脚本攻击类的库 app.use(helmet()); // 给请求添加prefix app.setGlobalPrefix('api/v1'); // 全局使用管道 app.useGlobalPipes(new ValidationPipe()); await app.listen(3000, () => { Logger.log('服务已经启动,请访问localhost:3000'); }); } bootstrap();
-
2、在
cat.controller.ts
中使用提交过来的数据约束@Controller('cat') export class CatController { constructor(private readonly catService: CatService) {} @Post() @HttpCode(HttpStatus.CREATED) async create(@Body() createCatDto: CreateCatDto) { // 这里就不需要使用校验约束 Logger.log('-----------创建猫 start--------------'); Logger.log(createCatDto); Logger.log('-----------创建猫 end--------------'); return '创建猫'; } ... }
-
3、前端传递数据错误的提示
{ "statusCode": 400, "error": "Bad Request", "message": [ { "target": { "name": "哈士奇222", "age": "20" }, "value": "20", "property": "age", "children": [], "constraints": { "isInt": "必须的整数" } } ] }
三、约束@Param
接受的数据类型
-
1、安装包
npm i --save class-validator class-transformer
-
2、直接在
cat.controller.ts
中使用@Controller('cat') export class CatController { constructor(private readonly catService: CatService) {} ... @Get(':id') @HttpCode(HttpStatus.OK) async findOne( @Param('id', new ParseIntPipe()) id, // 使用内置的转换整数的管道 @Query() query: { [propsName: string]: any }, ) { Logger.log('-----------查找一个 start--------------'); Logger.log(id); Logger.log(query); Logger.log('-----------查找一个 end--------------'); return await this.catService.findOne(id); } ... }
四、自己创建管道生成验证规则
上面使用的是内置的管道约束,如果没有,我们可以自己创建约束管道
- 1、在
src
目录下创建一个文件夹pipe
-
2、使用命令生成管道
nest g pi pipe/parseInt nest g pi pipe/parseInt --no-spec # 不生成带测试文件的
-
3、书写管道代码
import { ArgumentMetadata, Injectable, PipeTransform, BadRequestException, } from '@nestjs/common'; @Injectable() export class ParseIntPipe implements PipeTransform<string, number> { transform(value: string, metadata: ArgumentMetadata): number { const val = parseInt(value, 10); if (isNaN(val)) { throw new BadRequestException('验证错误'); } return val; } }
-
4、直接在
cat.controller.ts
中使用(和内置的一样的使用)
五、自定义返回错误格式
-
1、命令方式生成自己的校验管道
nest g pi pipe/Validation --no-spec
-
2、管道的书写
/* * @Description:自定义管道,根据自己格式返回错误信息 * @Author: 水痕 * @Github: https://github.com/kuangshp * @Email: 332904234@qq.com * @Company: * @Date: 2019-07-24 14:26:27 * @LastEditors: 水痕 * @LastEditTime: 2019-07-24 14:46:45 */ import { ArgumentMetadata, Injectable, PipeTransform, BadRequestException, Logger, } from '@nestjs/common'; import { validate } from 'class-validator'; import { plainToClass } from 'class-transformer'; import * as _ from 'lodash'; @Injectable() export class ValidationPipe implements PipeTransform<any> { async transform(value: any, metadata: ArgumentMetadata) { const { metatype } = metadata; if (!metatype || !this.toValidate(metatype)) { return value; } const object = plainToClass(metatype, value); const errors = await validate(object); Logger.log(errors); if (errors.length > 0) { // 遍历全部的错误信息,返回给前端 const errorMessage = errors.map(item => { return { currentValue: item.value, [item.property]: _.values(item.constraints)[0], }; }); throw new BadRequestException(errorMessage); } return value; } private toValidate(metatype: any): boolean { const types = [String, Boolean, Number, Array, Object]; return !types.includes(metatype); } }
-
3、使用方式和上面的一样的
-
4、返回的错误提示
{ "data": { "error": [ { "currentValue": "哈士奇21111111111111", "name": "长度不能超过10" }, { "age": "年龄不能为空" } ] }, "message": "请求失败", "code": 1, "url": "/api/v1/cat" }