使用 class-transformer 解決欄位名不一致轉化問題

kexb發表於2024-10-27

前言

在前後端開發中,資料傳輸格式的一致性是至關重要的。尤其是在不同程式語言之間傳遞資料時,欄位命名規則的不同可能會導致前端無法正確解析後端返回的資料。我們知道一般欄位的命名規則一般是 駝峰式 和 下劃線 的方式,一般情況下 下線劃 是定義mysql 屬性欄位的時候使用,而 java 跟 ts 基本都是採用駝峰式命名。

為了解決這個前端無法正確解析後端返回的資料,使用 class-transformer 可以幫助我們在物件轉換時處理欄位命名的差異,確保前端能夠正確接收到資料。

使用 class-transformer 進行欄位轉換

  1. 定義 user 實體

export class User {
  id: number;
  name: string;
  username: string;
  createdAt: string;
  updatedAt: string;

  constructor(
    id: number,
    name: string,
    username: string,
    createdAt: string,
    updatedAt: string
  ) {
    this.id = id;
    this.name = name;
    this.username = username;
    this.createdAt = createdAt;
    this.updatedAt = updatedAt;
  }
}
  1. 定義mock api
import {ApiInjector, MockApiInterface} from "@yunzhi/ng-mock-api";

export class UserApi implements MockApiInterface {
  getInjectors(): ApiInjector[] {
    return [
      {
        method: 'GET',
        url: '/user/getById/:id',
        description: '任務列表',
        // 模擬返回的資料
        result: {
          id: 1,
          name: '張三',
          username: 'zhangsan',
          created_at: '2021-01-01 00:00:00',
          updated_at: '2021-01-01 00:00:00'
        }
      }
    ];
  }
}
  1. 實現服務
import { Injectable } from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {Observable} from "rxjs";
import {User} from "../entity/user";

@Injectable({
  providedIn: 'root'
})
export class UserService {

  constructor(private httpClient: HttpClient) {
  }

  getById(id: number): Observable<User> {
    return this.httpClient.get<User>(`/user/getById/${id}`);
  }
}
  1. 元件中使用服務
@Component({
  selector: 'app-root',
  template: `
    <div *ngIf="user">
    <h1>名稱:{{ user.name }}</h1>
    <p>使用者名稱: {{ user.username }}</p>
    <p>建立時間: {{ user.createdAt }}</p>
    <p>修改時間: {{ user.updatedAt }}</p>
    </div>
  `
})
export class AppComponent implements OnInit{
  user: User = {} as User;

  constructor(private userService: UserService) {
  }

  ngOnInit(): void {
    this.userService.getById(1).subscribe((user: User) => {
      this.user = user;
    });
  }
}

這裡我發現當前 createdAt 和 updatedAt 無法接收到值

image.png

  1. 安裝 class-transformer
npm install class-transformer

配置tsconfig.json檔案以支援裝飾器

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  }
}
  1. 重構 user 實體
import { Expose } from 'class-transformer';

export class User {
  id: number;
  name: string;
  username: string;

  @Expose({ name: 'created_at' })
  createdAt: string; // 保持為字串型別

  @Expose({ name: 'updated_at' })
  updatedAt: string; // 保持為字串型別
}
  1. 接收到的值進行轉換
this.userService.getById(1).subscribe((user: User) => {
  this.user = plainToInstance(User, user);
});

到這裡我們發現這個就可以解決轉換問題了

image.png

總結

到這裡我們解決欄位不一致的問題,這個功能很像 JAVA 使用 @JsonAlias 註解 使用起來很方便

相關文章