從 JSON 物件初始化 TypeScript 物件
Shuvayan Ghosh Dastidar
2023年1月30日

使用 TypeScript 處理 API 時,資料以字串形式序列化,以便通過 Internet 協議進行傳輸。但是,使用從 API 接收到的資料需要在需要時反序列化為 TypeScript 類或物件。
本文將演示如何將接收到的物件轉換為 TypeScript 型別的不同方法。這樣就可以訪問這種型別的支援、IDE 完成和其他功能。
將物件反序列化為 TypeScript 物件
JavaScript 中的 JSON 包很好地將普通物件解析為 TypeScript 物件。以下程式碼段演示瞭如何將 JSON 字串解析為 TypeScript 物件。
var jsonString : string =`{
"id": 1,
"title" : "The Great Gatsby",
"numPages" : 218
}`
interface BookInfo {
id : number ;
title : string ;
numPages : number ;
}
var Book : BookInfo = JSON.parse(jsonString);
console.log(Book);
console.log(Book.title);
輸出:
{
"id": 1,
"title": "The Great Gatsby",
"numPages": 218
}
"The Great Gatsby"
jsonString
可能是 API 響應的一部分,它以序列化字串的形式出現。因此,如本例所示,變數 Book
將像普通 TypeScript 物件一樣提供補全。
但是,這在類物件中包含函式和建構函式的情況下不起作用。考慮以下程式碼段,它演示了這一點。
class Animal{
name : string;
legs : number;
constructor(name : string, legs : number){
this.name = name;
this.legs = legs;
}
getName(){
return this.name;
}
}
var jsonString : string = `{
"name" : "Tiger",
"legs" : 4
}`
var animalObj : Animal = JSON.parse(jsonString)
// this will give an error - animalObj.getName is not a function
animalObj.getName();
因此,從 animalObj
變數中,我們可以訪問 name
和 legs
欄位。但是,我們無法訪問 getName()
函式,因為它是 Animal
類的一部分,無法直接解析但已初始化。
更改 Animal
類,以便 JSON 解析的物件可以訪問成員函式。解析的物件必須被初始化。
class Animal{
name : string;
legs : number;
constructor(name : string, legs : number){
this.name = name;
this.legs = legs;
}
getName(){
return this.name;
}
toObject(){
return {
name : this.name,
legs : this.legs.toString()
}
}
serialize() {
return JSON.stringify(this.toObject());
}
static fromJSON(serialized : string) : Animal {
const animal : ReturnType<Animal["toObject"]> = JSON.parse(serialized);
return new Animal(
animal.name,
animal.legs
)
}
}
var jsonString : string = `{
"name" : "Tiger",
"legs" : 4
}`
var animalObj : Animal = Animal.fromJSON(jsonString);
console.log(animalObj)
// this will work now
console.log(animalObj.getName());
輸出:
Animal: {
"name": "Tiger",
"legs": 4
}
"Tiger"
反序列化 Typescript 物件的動態方法
現在,這種方法需要準確瞭解類的屬性。下面討論了一種更動態的反序列化 typescript 物件的方法。
在這種方法中,類的作者可以完全控制反序列化邏輯,並且可以使用多個類,如圖所示。
interface Serializable<T> {
deserialize(input : Object) : T;
}
class Furniture implements Serializable<Furniture> {
price : number;
deserialize(input) {
this.price = Number(input.price);
return this;
}
getPrice(){
return this.price;
}
}
class Chair implements Serializable<Chair> {
id : string;
furniture : Furniture;
deserialize(input) {
this.id = input.id;
this.furniture = new Furniture().deserialize(input.furniture);
return this;
}
}
var jsonString = `{
"id" : "2323",
"furniture" : {
"price": 3000
}
}`
var chair = new Chair().deserialize(JSON.parse(jsonString))
console.log(chair)
輸出:
Chair: {
"id": "2323",
"furniture": {
"price": 3000
}
}