Nest 管道:数据验证与转换的利器

管道简介

Nest.js 的管道(Pipes)用于处理输入数据的转换和验证。可以执行以下任务:

  1. 验证(Validation):确保传入请求的数据符合某些标准,如果数据无效,则可以抛出异常。
  2. 转换(Transformation):将输入数据转换成期望的形式,例如从字符串转换成整数,或者从用户输入的日期字符串转换为 Date 对象。

管道有两种类型:

  1. 内置管道 :Nest.js 提供了一些内置的管道,例如 ValidationPipeParseIntPipe 等。
  2. 自定义管道:用户可以创建自定义管道来满足特定的需求。

我们先来介绍内置管道。

内置管道

Nest 内置的 Pipe:

  • ValidationPipe
  • ParseIntPipe
  • ParseBoolPipe
  • ParseArrayPipe
  • ParseUUIDPipe
  • DefaultValuePipe
  • ParseEnumPipe
  • ParseFloatPipe
  • ParseFilePipe

创建项目:

bash 复制代码
nest new pipe-test -p npm

ParseIntPipe

ParseIntPipe 转换参数为整数,无法转换或者转换后不是整数则抛出异常:

访问页面可以看出 age 是字符串,因为字符串 + 数字才会拼接:

我们使用 ParseIntPipe

正确相加:

传递一个无法转换整数的会报错:

我们还可以自定义错误:

重新访问:

这里也可以通过 exceptionFactory 选项自定义异常工厂函数,抛出异常,让异常过滤器自己处理。

ParseFloatPipe

ParseFloatPipe 是将参数转换为浮点数:

访问下:

同样支持 new ParseFloatPipe 的形式,可传入 errorHttpStatusCode 和 exceptionFactory 选项自定义错误。

ParseBoolPipe

ParseBoolPipe 用于将输入的字符串转换为布尔值。如果输入的值无法转换为布尔值,则会抛出异常。

ParseEnumPipe

ParseEnumPipe 用于确保输入的值是特定枚举中的一个有效值。如果输入的值不在枚举中,则会抛出异常。

如果 role 的值不是 admin 或 user,则会抛出 BadRequestException。

也同样可以通过 errorHttpStatusCode 和 exceptionFactory 来自定义错误。

ParseUUIDPipe

ParseUUIDPipe 用于验证输入的字符串是否是有效的 UUID(通用唯一标识符)。如果不是有效的 UUID,则会抛出异常。

我们用 uuid 包可以生成 uuid:


DefaultValuePipe

DefaultValuePipe 用于为参数提供一个默认值:

ParseArrayPipe

用于将客户端发送的字符串数组解析为实际的数组类型:

先安装 class-validator 包,这是可以用装饰器和非装饰器两种方式对 class 属性做验证的库。

再安装 class-transformer 包,它是把普通对象转换为对应的 class 实例的包。

bash 复制代码
npm install class-validator class-transformer -D


还剩下 ValidationPipe 和 ParseFilePipe,之后再讲。

使用管道的 4 种方式

管道不仅支持对某个参数级别生效,也能对整个 Controller 、方法、全局都生效。

typescript 复制代码
// 参数级别的 Pipes
@Get(':id')
getUserById(@Param('id', ParseIntPipe) id: number) {
  // ...
}

// Controller 生效
@Controller('users')
@UsePipes(ValidationPipe)
export class UsersController {
  // ...
}

// 方法级别的 Pipes
@Controller('users')
export class UsersController {
  @Post()
  @UsePipes(ValidationPipe)
  createUser(@Body() createUserDto: CreateUserDto) {
    // ...
  }
}

// 全局 Pipes
import { Module } from '@nestjs/common';
import { APP_PIPE } from '@nestjs/core';
import { ValidationPipe } from './pipes/validation.pipe';

@Module({
  providers: [
    {
      provide: APP_PIPE,
      useClass: ValidationPipe,
    },
  ],
})
export class AppModule {}

创建自定义管道

创建自定义管道,需要实现 PipeTransform 接口,并定义 transform 方法。

下面管道,它将输入字符串转换为整数:

typescript 复制代码
import { PipeTransform, Injectable, ArgumentMetadata, 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('Validation failed');
    }
    return val;
  }
}

使用这个自定义管道:

typescript 复制代码
import { Controller, Get, Query, UsePipes } from '@nestjs/common';
import { ParseIntPipe } from './parse-int.pipe';

@Controller('numbers')
export class NumbersController {
  @Get()
  @UsePipes(ParseIntPipe)
  async getNumber(@Query('num') num: number): Promise<number> {
    // num 参数已经被 ParseIntPipe 转换为整数
    return num;
  }
}

当客户端发起请求并传递 num 查询参数时,ParseIntPipe 会自动将 num 转换为整数类型,然后传递给 getNumber 方法。

相关推荐
Brookty1 分钟前
【JavaEE】线程安全-内存可见性、指令全排序
java·开发语言·后端·java-ee·线程安全·内存可见性·指令重排序
智能化咨询13 分钟前
【Linux】【实战向】Linux 进程替换避坑指南:从理解 bash 阻塞等待,到亲手实现能执行 ls/cd 的 Shell
前端·chrome
Anson Jiang15 分钟前
浏览器标签页管理:使用chrome.tabs API实现新建、切换、抓取内容——Chrome插件开发从入门到精通系列教程06
开发语言·前端·javascript·chrome·ecmascript·chrome devtools·chrome插件
风象南18 分钟前
SpringBoot Jar包冲突在线检测
后端
掘金安东尼18 分钟前
黑客劫持:周下载量超20+亿的NPM包被攻击
前端·javascript·面试
程序员爱钓鱼20 分钟前
Go语言实战案例 — 项目实战篇:任务待办清单 Web 应用
后端·google·go
剑亦未配妥1 小时前
移动端触摸事件与鼠标事件的触发机制详解
前端·javascript
Cyan_RA92 小时前
SpringMVC @RequestMapping的使用演示和细节 详解
java·开发语言·后端·spring·mvc·ssm·springmvc
人工智能训练师7 小时前
Ubuntu22.04如何安装新版本的Node.js和npm
linux·运维·前端·人工智能·ubuntu·npm·node.js
Seveny077 小时前
pnpm相对于npm,yarn的优势
前端·npm·node.js