温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Nest.js参数校验和自定义返回数据格式的示例分析

发布时间:2021-03-29 10:53:00 来源:亿速云 阅读:574 作者:小新 栏目:开发技术

这篇文章主要介绍Nest.js参数校验和自定义返回数据格式的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

0x0 参数校验

参数校验大部分业务是使用 Nest.js 中的管道 方法实现,具体可以查阅文档 。不过编写过程中遇到一些问题,虽然文档讲得比较晦涩。

在做个查询接口,里面包含一些参数,做成 dto 结构数据:

import { ApiProperty } from '@nestjs/swagger' export class QueryUserDto {  @ApiProperty({  required: false,  description: '页码'  })  readonly currentPage: number  @ApiProperty({  required: false,  description: '条数'  })  readonly pageSize: number  @ApiProperty({  required: false,  description: '用户账号'  })  readonly username?: string  @ApiProperty({  required: false,  description: '用户状态'  })  readonly activeStatus: number  @ApiProperty({  required: false,  description: '排序的方式: ASC, DESC'  })  readonly order: 'DESC' | 'ASC' }  TYPESCRIPT

在 @Query 请求传入对应的参数,发现得到的数据类型都是 String ,然后查阅相关文档才明白还需要 class-transformer 的 Type 进行转换:

import { ApiProperty } from '@nestjs/swagger' import { Type } from 'class-transformer' export class QueryUserDto {  @ApiProperty({  required: false,  description: '页码'  })  @Type(() => Number)  readonly currentPage: number = 1  @ApiProperty({  required: false,  description: '条数'  })  @Type(() => Number)  readonly pageSize: number = 10  @ApiProperty({  required: false,  description: '用户账号'  })  readonly username?: string  @ApiProperty({  required: false,  description: '用户状态'  })  @Type(() => Number)  readonly activeStatus: number = 3  @ApiProperty({  required: false,  description: '排序的方式: ASC, DESC'  })  readonly order: 'DESC' | 'ASC' = 'DESC' }

然后在 ValidationPipe 管道方法里开启 transform 选项:

app.useGlobalPipes(  new ValidationPipe({  transform: true  }) )

或者在 app.modules.ts 注入:

import { ValidationPipe } from '@nestjs/common' import { APP_PIPE } from '@nestjs/core' @Module({  imports: [  // ...  ],  controllers: [AppController],  providers: [  {   provide: APP_PIPE,   useValue: new ValidationPipe({   transform: true   })  }  ] })

俩者使用方法区别于程序的是否混合应用类型。

我这边为了省事直接写在全局方法里,最终到 service 拿到的数据就是经过管道业务处理过的数据,不需要在 service 层进行大量的数据类型判断。

0x1 自定义返回数据格式

在 controller 返回的数据都是从数据库表结构而来:

{  "id": "d8d5a56c-ee9f-4e41-be48-5414a7a5712c",  "username": "Akeem.Cremin",  "password": "$2b$10$kRcsmN6ewFC2GOs0TEg6TuvDbNzf1VGCbQf2fI1UeyPAiZCq9rMKm",  "email": "Garrett87@hotmail.com",  "nickname": "Wallace Nicolas",  "role": "user",  "isActive": true,  "createdTime": "2021-03-24T15:24:26.806Z",  "updatedTime": "2021-03-24T15:24:26.806Z" }

如果需要定义最终返回接口的数据格式例如:

{  "statusCode": 200,  "message": "获取成功",  "data": {   "id": "d8d5a56c-ee9f-4e41-be48-5414a7a5712c",   "username": "Akeem.Cremin",   "password": "$2b$10$kRcsmN6ewFC2GOs0TEg6TuvDbNzf1VGCbQf2fI1UeyPAiZCq9rMKm",   "email": "Garrett87@hotmail.com",   "nickname": "Wallace Nicolas",   "role": "user",   "isActive": true,   "createdTime": "2021-03-24T15:24:26.806Z",   "updatedTime": "2021-03-24T15:24:26.806Z"  } }

这里就需要做个自定义成功请求拦截器:

nest g in shared/interceptor/transform
import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } from '@nestjs/common' import { Observable } from 'rxjs' import { map } from 'rxjs/operators' import { Request } from 'express' interface Response<T> {  data: T } @Injectable() export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {  intercept(context: ExecutionContext, next: CallHandler<T>): Observable<any> {  const request = context.switchToHttp().getRequest<Request>()  Logger.log(request.url, '正常接口请求')  return next.handle().pipe(   map(data => {   return {    data: data,    statusCode: 200,    message: '请求成功'   }   })  )  } }

然后在 app.module.ts 引入即可使用:

import { ValidationPipe } from '@nestjs/common' import { APP_INTERCEPTOR } from '@nestjs/core' import { TransformInterceptor } from '@/shared/interceptor/transform.interceptor' @Module({  imports: [  // ...  ],  controllers: [AppController],  providers: [  {   provide: APP_INTERCEPTOR,   useClass: TransformInterceptor  }  ] })

不过 APP_INTERCEPTOR 排序要注意,TransformInterceptor 最好放在第一个,否则会失效。

错误过滤器:

nest g f shared/filters/httpException
import { ArgumentsHost, Catch, ExceptionFilter, HttpException, Logger } from '@nestjs/common' import { Response, Request } from 'express' @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter {  catch(exception: HttpException, host: ArgumentsHost) {  const context = host.switchToHttp()  const response = context.getResponse<Response>()  const request = context.getRequest<Request>()  const status = exception.getStatus()  const message = exception.message  Logger.log(`${request.url} - ${message}`, '非正常接口请求')  response.status(status).json({   statusCode: status,   message: message,   path: request.url,   timestamp: new Date().toISOString()  })  } }

然后在 app.module.ts 引入即可使用:

import { ValidationPipe } from '@nestjs/common' import { APP_FILTER } from '@nestjs/core' import { HttpExceptionFilter } from '@/shared/filters/http-exception.filter' @Module({  imports: [  // ...  ],  controllers: [AppController],  providers: [  {   provide: APP_FILTER,   useClass: HttpExceptionFilter  }  ] })

0x2 隐藏实体类中的某个字段

本来想使用 @Exclude 属性来隐藏数据库中一些敏感的字段,但发现无法满足特殊的需求,如果是返回单条实例可以实现隐藏,但是我有个 findAll 就无法实现了,上面在 Serialization | NestJS - A progressive Node.js framework 文档里说的非常详细,不过这里还有个办法。首先在实力类敏感数据字段上添加属性:

import { BaseEntity, Entity, Column, PrimaryGeneratedColumn } from 'typeorm' @Entity('user') export class UserEntity extends BaseEntity {  @PrimaryGeneratedColumn('uuid', {   comment: '用户编号'  })  id: string  @Column({   type: 'varchar',   length: 50,   unique: true,   comment: '登录用户'  })  username: string  @Column({   type: 'varchar',   length: 200,   select: false,   comment: '密码'  })  password: string

select: false 可以在返回查询结果隐藏这个字段,但所有涉及到这个字段查询必须添加这个字段,比如我在 user.service.ts 登录查询中:

const user = await getRepository(UserEntity)    .createQueryBuilder('user')    .where('user.username = :username', { username })    .addSelect('user.password')    .getOne()

.addSelect('user.password') 添加这个属性查询将会包括 password 这个字段,否则普通查询的方法不会包括这个字段。

以上是“Nest.js参数校验和自定义返回数据格式的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI