NestJS 序列化

2023-09-08 17:41 更新

序列化(Serialization)是一個(gè)在網(wǎng)絡(luò)響應(yīng)中返回對(duì)象前的過程。 這是一個(gè)適合轉(zhuǎn)換和凈化要返回給客戶的數(shù)據(jù)的地方。例如,應(yīng)始終從最終響應(yīng)中排除敏感數(shù)據(jù)(如用戶密碼)。此外,某些屬性可能需要額外的轉(zhuǎn)換,比方說,我們只想發(fā)送一個(gè)實(shí)體的子集。手動(dòng)完成這些轉(zhuǎn)換既枯燥又容易出錯(cuò),并且不能確定是否覆蓋了所有的情況。

譯者注: Serialization 實(shí)現(xiàn)可類比 composer 庫(kù)中 fractal ,響應(yīng)給用戶的數(shù)據(jù)不僅僅要剔除設(shè)計(jì)安全的屬性,還需要剔除一些無用字段如 create_time, delete_time, update_time 和其他屬性。在 JAVA 的實(shí)體類中定義 N 個(gè)屬性的話就會(huì)返回 N 個(gè)字段,解決方法可以使用范型編程,否則操作實(shí)體類回影響數(shù)據(jù)庫(kù)映射字段。

概要

為了提供一種直接的方式來執(zhí)行這些操作, Nest 附帶了這個(gè) ClassSerializerInterceptor 類。它使用類轉(zhuǎn)換器來提供轉(zhuǎn)換對(duì)象的聲明性和可擴(kuò)展方式?;诖祟惢A(chǔ)下,可以從類轉(zhuǎn)換器中獲取方法和調(diào)用 classToPlain() 函數(shù)返回的值。要這樣做,可以將由class-transformer裝飾器提供的規(guī)則應(yīng)用在實(shí)體/DTO 類中,如下所示:

排除屬性

我們假設(shè)要從一個(gè)用戶實(shí)體中自動(dòng)排除password屬性。我們給實(shí)體做如下注釋:

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);
  }
}

然后,直接在控制器的方法中調(diào)用就能獲得此類的實(shí)例。

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

我們必須返回一個(gè)類的實(shí)體。如果你返回一個(gè)普通的 JavaScript 對(duì)象,例如,{user: new UserEntity()},該對(duì)象將不會(huì)被正常序列化。

提示: @ClassSerializerInterceptor() 裝飾器來源于 @nestjs/common 包。

現(xiàn)在當(dāng)你調(diào)用此服務(wù)時(shí),將收到以下響應(yīng)結(jié)果:

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

注意,攔截器可以應(yīng)用于整個(gè)應(yīng)用程序(見這里)。攔截器和實(shí)體類聲明的組合確保返回 UserEntity 的任何方法都將確保刪除 password 屬性。這給你一個(gè)業(yè)務(wù)規(guī)則的強(qiáng)制、集中的評(píng)估。

公開屬性

您可以使用 @Expose() 裝飾器來為屬性提供別名,或者執(zhí)行一個(gè)函數(shù)來計(jì)算屬性值(類似于 getter 函數(shù)),如下所示。

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

變換

您可以使用 @Transform() 裝飾器執(zhí)行其他數(shù)據(jù)轉(zhuǎn)換。例如,您要選擇一個(gè)名稱 RoleEntity 而不是返回整個(gè)對(duì)象。

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

傳遞選項(xiàng)

你可能想要修改轉(zhuǎn)換函數(shù)的默認(rèn)行為。要覆蓋默認(rèn)設(shè)置,請(qǐng)使用 @SerializeOptions() 裝飾器來將其傳遞給一個(gè)options對(duì)象。

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

提示: @SerializeOptions() 裝飾器來源于 @nestjs/common 包。

通過 @SerializeOptions() 傳遞的選項(xiàng)作為底層 classToPlain() 函數(shù)的第二個(gè)參數(shù)傳遞。在本例中,我們自動(dòng)排除了所有以_前綴開頭的屬性。

Websockets 和 微服務(wù)

雖然本章展示了使用 HTTP 風(fēng)格的應(yīng)用程序的例子(例如,Express 或 Fastify ),但是 ClassSerializerInterceptor對(duì)于 WebSockets 和微服務(wù)的工作方式是一樣的,不管使用的是哪種傳輸方法。

更多

想了解有關(guān)裝飾器選項(xiàng)的更多信息,請(qǐng)?jiān)L問此頁(yè)面


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)