序列化(Serialization)是一個在網絡響應中返回對象前的過程。 這是一個適合轉換和凈化要返回給客戶的數據的地方。例如,應始終從最終響應中排除敏感數據(如用戶密碼)。此外,某些屬性可能需要額外的轉換,比方說,我們只想發(fā)送一個實體的子集。手動完成這些轉換既枯燥又容易出錯,并且不能確定是否覆蓋了所有的情況。
譯者注: Serialization 實現可類比 composer 庫中 fractal ,響應給用戶的數據不僅僅要剔除設計安全的屬性,還需要剔除一些無用字段如 create_time, delete_time, update_time 和其他屬性。在 JAVA 的實體類中定義 N 個屬性的話就會返回 N 個字段,解決方法可以使用范型編程,否則操作實體類回影響數據庫映射字段。
為了提供一種直接的方式來執(zhí)行這些操作, Nest 附帶了這個 ClassSerializerInterceptor 類。它使用類轉換器來提供轉換對象的聲明性和可擴展方式?;诖祟惢A下,可以從類轉換器中獲取方法和調用 classToPlain() 函數返回的值。要這樣做,可以將由class-transformer裝飾器提供的規(guī)則應用在實體/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 屬性。這給你一個業(yè)務規(guī)則的強制、集中的評估。
您可以使用 @Expose() 裝飾器來為屬性提供別名,或者執(zhí)行一個函數來計算屬性值(類似于 getter 函數),如下所示。
@Expose()
get fullName(): string {
return `${this.firstName} ${this.lastName}`;
}
您可以使用 @Transform() 裝飾器執(zhí)行其他數據轉換。例如,您要選擇一個名稱 RoleEntity 而不是返回整個對象。
@Transform(role => role.name)
role: RoleEntity;
你可能想要修改轉換函數的默認行為。要覆蓋默認設置,請使用 @SerializeOptions() 裝飾器來將其傳遞給一個options對象。
@SerializeOptions({
excludePrefixes: ['_'],
})
@Get()
findOne(): UserEntity {
return {};
}
提示: @SerializeOptions() 裝飾器來源于 @nestjs/common 包。
通過 @SerializeOptions() 傳遞的選項作為底層 classToPlain() 函數的第二個參數傳遞。在本例中,我們自動排除了所有以_前綴開頭的屬性。
雖然本章展示了使用 HTTP 風格的應用程序的例子(例如,Express 或 Fastify ),但是 ClassSerializerInterceptor對于 WebSockets 和微服務的工作方式是一樣的,不管使用的是哪種傳輸方法。
想了解有關裝飾器選項的更多信息,請訪問此頁面。
更多建議: