Nest Validator 校验参数

缘起

在Nest Controller 对客户端参数校验并处理同意的异常结果 Message,例如 校验参数 1< name < 100, 响应不同的 Message " 请填写 name 长度 1 ~ 100 之间 !" 等等

  • 蹩脚写法
typescript 复制代码
@Controller('list')
export class ListController {
  @Post()
  addList(@Body() body): any {
    const { name } = body;
    if(name.length > 100) {
			.....
    }
  }
}

可以使用 class-validator 来完成对参数的校验,class-validator

示例

shell 复制代码
npm i --save class-validator class-transformer

or

shell 复制代码
yarn add class-validator class-transformer

class-validator 和 class-transformer 是一个作者,前者提供数据的校验,后者提供对复杂数据结构的类型转换

使用之前我们先定义一个 Dto 例如 dto.ts 👇🏻

typescript 复制代码
class FooBodyDto {
  @IsString()
  @Length(1, 100, {
    message: '请输入1-100长度之间的名称',
  })
  name: string;
}

export { FooBodyDto };

使用这个 dto 来校验我们需要的参数

处理结果 还可以使用 validateOrReject 具体参考文档

typescript 复制代码
@Controller('list')
export class ListController {
  @Post()
  async addList(@Body() body): Promise<any> {
    const { name } = body;
    const post = plainToClass(FooBodyDto, { name });
    const errors = await validate(post);

    if (errors.length > 0) {
      const msgs = [];
      errors.forEach((item) => {
        msgs.push(Object.values(item.constraints)[0]);
      });
      throw new HttpException(String(msgs), 500);
    } else {
      // ...
    }
  }
}

这段代码,使用 plainToClass 来把客户端的参数转换为 validate 需要的类,然后使用 Dto 里面的校验来对我们的参数进行校验,最好返回的 errors 然后我们对里面的校验结果我们自定义的文案也就是 message 进行合并处理最后用HttpException 异常状态 来抛给 客户端。

完整的逻辑我们还需要一个 Res 拦截器来处理这个异常 例如 response-interceptor.interceptor.ts 👇🏻

typescript 复制代码
import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  BadGatewayException,
} from '@nestjs/common';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

@Injectable()
export class ResponseInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      map((data) => {
        return {
          success: true,
          data,
        };
      }),
      catchError((error) => {
        // 处理异常的数据结构
        return throwError(
          () =>
            new BadGatewayException({
              success: false,
              code: 500,
              message: error.message,
            }),
        );
      }),
    );
  }
}

class-validator

class-validator 来校验参数,除了以上直接使用 validate 、validateOrReject 、还可以直接在 body 上校验

class-validator 更多参考文档这里就不做过多赘述

typescript 复制代码
import { Body, Controller, Post, UsePipes, ValidationPipe } from '@nestjs/common';
import { CreateUserDto } from './create-user.dto';

@Controller('users')
export class UsersController {
  @Post()
  @UsePipes(new ValidationPipe())
  create(@Body() createUserDto: CreateUserDto) {
    // 在这里,如果请求体不满足 CreateUserDto 的验证规则,
    // NestJS 将自动返回一个带有错误详情的 400 Bad Request 响应。

    // 如果验证成功,你可以安全地使用 createUserDto
    // ...
  }
}

class-transformer

class-transformer 不仅可以对 dto 的转换 还可以执行参数的转换 例如

class-transformer 更多参考文档这里就不做过多赘述

  • classToPlain & plainToClass 就是实例和对象的相互转化啦
typescript 复制代码
import { classToPlain } from 'class-transformer';

let user = new User();
// ...给 user 赋值...

let plainUser = classToPlain(user);

------- 分割线 -------


import { plainToClass } from 'class-transformer';

let plainUser = { /* ... */ };

let user = plainToClass(User, plainUser);
typescript 复制代码
import { Exclude, Expose, Transform } from 'class-transformer';

@Exclude() 
export class User {
  id: number;

  @Expose()
  name: string;

  @Expose()
  @Transform(value => value.toUpperCase(), { toClassOnly: true })
  email: string;
}
  • @Exclude():此装饰器用于指定不应该被包含在转换过程中的属性。如果你在类的定义中使用了 @Exclude() 装饰器,那么默认情况下将不包含任何属性,只有被 @Expose() 装饰的属性才会被包含。这对于处理敏感信息非常有用,例如,你可能想要在转换用户对象时排除密码字段。

  • @Expose():此装饰器用于指定应该被包含在转换过程中的属性。如果你没有在类的定义中使用 @Exclude() 装饰器,那么默认情况下会包含所有属性,使用 @Expose() 装饰器在这种情况下没有实际效果。然而,如果你使用了 @Exclude(),那么只有被 @Expose() 装饰的属性才会被包含。

  • @Transform()则是对特定属性的转换,如email 就被 toUpperCase 转换为大写

相关推荐
无双_Joney2 小时前
[四期 - 4] NestJS专栏 - 征召一下大家的意见,非常想知道大家都想看看Nest的哪些方面
前端·后端·nestjs
海上彼尚5 小时前
Nodejs也能写Agent - 17.LangGraph篇 - Checkpointer 与 Memory
前端·javascript·人工智能·langchain·node.js
狂师8 小时前
还在手写测试报告?推荐一款 AI 测试Skill:只需一句指令,自动生成专业定制化测试报告!
人工智能·测试·全栈
Karl_wei9 小时前
Harness 企业级落地(二) - 让 AI 读懂项目
程序员·openai·全栈
特立独行的猫a9 小时前
HarmonyOS鸿蒙PC三方库移植:Node.js 三方库鸿蒙 PC 移植指南
华为·node.js·node·harmonyos·三方库移植·鸿蒙pc
jump_jump21 小时前
Kysely 源码解剖:类型安全 SQL 如何走到 AST
node.js·orm·源码阅读
星栈1 天前
深度复盘:比 EventLoop 更隐蔽!Node 微任务堆积引发的线上接口雪崩事故
后端·node.js
万敏1 天前
Vue3 全栈实战第二周:Pinia + Vite + Router + axios 完整记录
vue.js·node.js·全栈
大家的林语冰1 天前
✌️ Deno 2.9 来了,ESM 直接导入 CSS,甚至能开发桌面应用?!
前端·javascript·node.js
糖墨夕1 天前
AI Agent技术栈选择:Vue3 + NestJS + TypeScript 为什么是绝佳组合
前端·nestjs