序列化是在网络响应中返回对象之前发生的过程。这是一个提供转换和清理要返回给客户端的数据的规则的合适地方。例如,密码等敏感数据应始终从响应中排除。或者,某些属性可能需要额外的转换,例如仅发送实体的属性子集。手动执行这些转换可能很繁琐且容易出错,并且可能让您不确定是否已涵盖所有情况。
概述
Nest 提供了内置功能,可帮助确保以简单的方式执行这些操作。ClassSerializerInterceptor
拦截器使用强大的 class-transformer 包来提供一种声明性和可扩展的对象转换方式。它执行的基本操作是获取方法处理程序返回的值并应用 class-transformer 中的 instanceToPlain()
函数。在此过程中,它可以将 class-transformer
装饰器表达的规则应用于实体/DTO 类,如下所述。
序列化不适用于 StreamableFile 响应。
排除属性
假设我们想要自动从用户实体中排除 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() {{ '}' }}
,则该对象将无法正确序列化。
The ClassSerializerInterceptor
is imported from @nestjs/common
.
请求此端点时,客户端会收到以下响应:
{
"id": 1,
"firstName": "Kamil",
"lastName": "Mysliwiec"
}
请注意,拦截器可以在整个应用程序范围内应用(如此处所述)。拦截器和实体类声明的组合确保返回UserEntity
的任何方法都一定会删除password
属性。这为您提供了集中执行此业务规则的措施。
公开属性
您可以使用@Expose()
装饰器为属性提供别名,或执行函数来计算属性值(类似于getter函数),如下所示。
@Expose()
get fullName(): string {
return `${this.firstName} ${this.lastName}`;
}
转换
您可以使用 @Transform()
装饰器执行额外的数据转换。例如,以下构造返回 RoleEntity
的 name 属性,而不是返回整个对象。
@Transform(({ value }) => value.name)
role: RoleEntity;
传递选项
您可能想要修改转换函数的默认行为。要覆盖默认设置,请使用 @SerializeOptions()
装饰器将它们传递到 options
对象中。
@SerializeOptions({
excludePrefixes: ['_'],
})
@Get()
findOne(): UserEntity {
return new UserEntity();
}
@SerializeOptions()
装饰器从 @nestjs/common
导入。
通过 @SerializeOptions()
传递的选项作为底层 instanceToPlain()
函数的第二个参数传递。在此示例中,我们自动排除所有以 _
前缀开头的属性。
示例
此处 提供了一个工作示例。
WebSockets 和微服务
虽然本章展示了使用 HTTP 样式应用程序(例如 Express 或 Fastify)的示例,但 ClassSerializerInterceptor
对于 WebSockets 和微服务的作用相同,无论使用哪种传输方法。
了解更多
阅读有关 class-transformer
包提供的可用装饰器和选项的更多信息此处。