NestJS 序列化

2023-09-08 17:41 更新

序列化(Serialization)是一个在网络响应中返回对象前的过程。 这是一个适合转换和净化要返回给客户的数据的地方。例如,应始终从最终响应中排除敏感数据(如用户密码)。此外,某些属性可能需要额外的转换,比方说,我们只想发送一个实体的子集。手动完成这些转换既枯燥又容易出错,并且不能确定是否覆盖了所有的情况。

译者注: Serialization 实现可类比 composer 库中 fractal ,响应给用户的数据不仅仅要剔除设计安全的属性,还需要剔除一些无用字段如 create_time, delete_time, update_time 和其他属性。在 JAVA 的实体类中定义 N 个属性的话就会返回 N 个字段,解决方法可以使用范型编程,否则操作实体类回影响数据库映射字段。

概要

为了提供一种直接的方式来执行这些操作, Nest 附带了这个 ClassSerializerInterceptor 类。它使用类转换器来提供转换对象的声明性和可扩展方式。基于此类基础下,可以从类转换器中获取方法和调用 classToPlain() 函数返回的值。要这样做,可以将由class-transformer装饰器提供的规则应用在实体/DTO 类中,如下所示:

排除属性

我们假设要从一个用户实体中自动排除password属性。我们给实体做如下注释:

import { Exclude } from 'class-transformer';

export class UserEntity {
  id: number;
  firstName: string;
  lastName: string;

  @Exclude()
  password: string;

  constructor(partial: Partial<UserEntity>) {
    Object.assign(this, partial);
  }
}

然后,直接在控制器的方法中调用就能获得此类的实例。

@UseInterceptors(ClassSerializerInterceptor)
@Get()
findOne(): UserEntity {
  return new UserEntity({
    id: 1,
    firstName: 'Kamil',
    lastName: 'Mysliwiec',
    password: 'password',
  });
}

我们必须返回一个类的实体。如果你返回一个普通的 JavaScript 对象,例如,{user: new UserEntity()},该对象将不会被正常序列化。

提示: @ClassSerializerInterceptor() 装饰器来源于 @nestjs/common 包。

现在当你调用此服务时,将收到以下响应结果:

{
  "id": 1,
  "firstName": "Kamil",
  "lastName": "Mysliwiec"
}

注意,拦截器可以应用于整个应用程序(见这里)。拦截器和实体类声明的组合确保返回 UserEntity 的任何方法都将确保删除 password 属性。这给你一个业务规则的强制、集中的评估。

公开属性

您可以使用 @Expose() 装饰器来为属性提供别名,或者执行一个函数来计算属性值(类似于 getter 函数),如下所示。

@Expose()
get fullName(): string {
  return `${this.firstName} ${this.lastName}`;
}

变换

您可以使用 @Transform() 装饰器执行其他数据转换。例如,您要选择一个名称 RoleEntity 而不是返回整个对象。

@Transform(role => role.name)
role: RoleEntity;

传递选项

你可能想要修改转换函数的默认行为。要覆盖默认设置,请使用 @SerializeOptions() 装饰器来将其传递给一个options对象。

@SerializeOptions({
  excludePrefixes: ['_'],
})
@Get()
findOne(): UserEntity {
  return {};
}

提示: @SerializeOptions() 装饰器来源于 @nestjs/common 包。

通过 @SerializeOptions() 传递的选项作为底层 classToPlain() 函数的第二个参数传递。在本例中,我们自动排除了所有以_前缀开头的属性。

Websockets 和 微服务

虽然本章展示了使用 HTTP 风格的应用程序的例子(例如,Express 或 Fastify ),但是 ClassSerializerInterceptor对于 WebSockets 和微服务的工作方式是一样的,不管使用的是哪种传输方法。

更多

想了解有关装饰器选项的更多信息,请访问此页面


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号