Skip to content

响应

向军大叔每晚八点在 抖音bilibli 直播

xj-small

序列化类(序列化)用于对返回给客户端的数据进行转换处理,比如控制用户密码字段不返回。序列化使用 class-transformer 扩展包完成,你也可以参考 nest官方文档的 序列化 章节。

声明定义

序列化使用拦截器进行处理,我们可以在全局,控制器,方法等处进行定义。

全局定义

修改 main.ts 主文件

import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common'
import { NestFactory, Reflector } from '@nestjs/core'
import { AppModule } from './app.module'

async function bootstrap() {
  const app = await NestFactory.create(AppModule)
 	...
 	//全局定义序列化拦截器
  app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)))
  await app.listen(3000)
}
bootstrap()

控制器

也可以在控制器中声明序列化

import { Body, ClassSerializerInterceptor, Controller, SerializeOptions, UseInterceptors } from '@nestjs/common'
...

@Controller('article')
@UseInterceptors(ClassSerializerInterceptor)

export class ArticleController {
  constructor(private readonly articleService: ArticleService) {}
	...
}

方法

也支持在方法中定义序列化

import { Body, ClassSerializerInterceptor, Controller, SerializeOptions, UseInterceptors } from '@nestjs/common'
...

@UseInterceptors(ClassSerializerInterceptor)
@Get(':id')
async findOne(@Param('id') id: string) {
	...
}

过滤选项

我们使用 @SerializeOptions() 对响进行配置,然后在响应类中对属性进行细节定义。

选项说明示例
strategyexposeAll:包含所有属性 excludeAll:排除所有属性@SerializeOptions({ strategy: 'exposeAll' })
excludePrefixes排除某个前缀的属性@SerializeOptions({ strategy: 'exposeAll',excludePrefixes: ['_'] })

下面是在控制器中对过滤选项的定义

import { Body, ClassSerializerInterceptor, Controller, SerializeOptions, UseInterceptors } from '@nestjs/common'
...

@Controller('article')
@UseInterceptors(ClassSerializerInterceptor)
//定义序列化选项
@SerializeOptions({ strategy: 'exposeAll' })

export class ArticleController {
  constructor(private readonly articleService: ArticleService) {}
  ...
}

响应类

下面定义 entitys/article.entitys.ts 类,来对响应结果进行处理

import { category, user } from '@prisma/client'
import { Exclude, Expose, Transform } from 'class-transformer'
import dayjs from 'dayjs'

export default class Article {
	//包含属性
  @Expose()
  title: string
	
	//排除属性
  @Exclude()
  content: string

	//序列化类的category栏目模型只包含标题
  @Transform(({ value, key, obj, type }) => {
		return obj[key].title
  })
  category: category

	//序列化类的日期使用dayjs进行格式化
  @Transform(({ value }) => dayjs(value).format('YYYY-MM-DD'))
  createdAt: Date
  
	//构造函数用于传递序列化类数据
  constructor(options: Partial<Article>={}) {
    Object.assign(this, options)
  }
}

使用方法

经过上面的学习,我们已经对nest.js 的响应掌握了,下面通过例子把这个过程走一遍。

响应类

下面通过文件 entitys/article.entity.ts 对响应结果进行定义

import { category } from '@prisma/client'
import { Exclude, Expose, Transform } from 'class-transformer'

export default class Article {
  @Expose()
  id: number

  @Exclude()
  content: string

  @Transform((value) => 'eee')
  title: string

  @Expose()
  category: category

  constructor(partial: Partial<Article> = {}) {
    Object.assign(this, partial)
  }
}

控制器

下面在控制器方法中使用响应类对返回客户端的结果进行处理,我们有多种方式可以操作。

import Article from './entitys/article.entity'
...

@Controller('article')
@UseInterceptors(ClassSerializerInterceptor)
@SerializeOptions({ strategy: 'excludeAll'})

export class ArticleController {
  constructor(private readonly articleService: ArticleService) {}

  @Get(':id')
  async findOne(@Param('id') id: string) {
    const article = await this.articleService.findOne(+id)
    return new Article(article)
  }
}

也可以使用 plainToClass 方法进行序列化,这时可以不用定义 UseInterceptorsSerializeOptions

@Controller()
export class AppController {
  @Get()
  getHello(@User() user: UserDto) {
    const users = new PrismaClient().user.findMany()
    return plainToClass(UserDto, users)
  }
}