2017-10-06 126 views
0

我有三個類Json爲打字稿對象。繼承

class Device{ 
    name:string; 
} 

class Mobile extends Device{ 
    number:string; 
} 

class Computer extends Device{ 
    macAddress:string; 
} 

和JSON

[{ 
'name':'mobile1', 
'number':'600 600 600', 
'class':'Mobile' 
},{ 
'name':'computer', 
'macAddress:'123123123', 
'class':'Computer' 
}] 

是有可能使用某種裝飾/或任何其他的獲得與正確的對象類型的設備清單。 我生產Json在我的網站,所以我還可以添加其他領域,改變結構,使打字稿對象列表corectly生成

我正在尋找任何解決方案沒有成功。

問候, 阿德里安

+1

嗨阿德里安,我覺得你的第三類應該被命名爲 '計算機'。除此之外,您可以嘗試將JSON對象解析爲let:Mobile或Computer,然後查看它是否有效。 – cdslijngard

+0

謝謝,現在正確 – Adrian

回答

1

我根據我的解決方案是什麼安德烈亞斯寫道:謝謝。 爲了達到正確的解決方案,我使用了令人敬畏的庫 json2typescript 。我的解決方案:

import {JsonObject, JsonProperty, JsonConverter, JsonCustomConvert, JsonConvert} from "json2typescript"; 


@JsonConverter 
class DeviceConverter implements JsonCustomConvert<DeviceDto[]> { 

    // We receive the instance and just serialize it with the standard json2typescript method. 
    serialize(device: DeviceDto[]): any { 
    const jsonConvert: JsonConvert = new JsonConvert(); 
    return jsonConvert.serialize(device); 
    } 

    // We receive a json object (not string) and decide 
    // based on the given properties whether we want to 
    // create an instance of Computer or Mobile. 
    deserialize(devicesInput: any): DeviceDto[] { 

    const jsonConvert: JsonConvert = new JsonConvert(); 


    let devices: Array<DeviceDto> = new Array<DeviceDto>(); 
    for (let device of devicesInput) { 
     if (device['type'] == 'mobile') { 
     let temp:MobileDeviceDto=jsonConvert.deserialize(device, MobileDeviceDto) 
     devices.push(temp); 
     } else if (device['type'] == 'rpi') { 
     devices.push(jsonConvert.deserialize(device, RaspberryPiDeviceDto)); 
     } 
    } 
    return devices; 
    } 


} 

@JsonObject 
export class DevicesDto { 
    @JsonProperty("devices", DeviceConverter) 
    devices: DeviceDto[] = []; 
} 


@JsonObject 
export class DeviceDto { 
    @JsonProperty("name", String) 
    name: string= undefined; 
    @JsonProperty("description", String) 
    description: string= undefined; 
    @JsonProperty("type", String) 
    type: string= undefined; 


} 

@JsonObject 
export class MobileDeviceDto extends DeviceDto { 
    @JsonProperty("number", String) 
    number: string = undefined; 
} 

@JsonObject 
export class RaspberryPiDeviceDto extends DeviceDto { 
    @JsonProperty("version", String) 
    version: string = undefined; 
} 

用法:

let jsonConvert: JsonConvert = new JsonConvert(); 
let devices: DeviceDto[] = jsonConvert.deserialize(data, DevicesDto).devices; 
this.subjectDeviceList.next(data); 

非常感謝你:)

1

我建議以下實現。請注意裏面的意見。它可能包含一些錯誤,因爲我實際上無法檢查代碼,所以可能需要做更多的工作。

基本思路:爲了使組件中的代碼變得簡單,您應該將數組包裝到一個對象中,這裏稱爲JsonDevices。然後你可以編寫一個自定義轉換器,讓魔法發生在轉換器內部。

// Custom serializer/deserializer. 
// You must implement serialize and deserialize methods 
@JsonConverter 
class DeviceConverter implements JsonCustomConvert<Device> { 

    // We receive the instance and just serialize it with the standard json2typescript method. 
    serialize(device: Device): any { 
     const jsonConvert: JsonConvert = new JsonConvert(); 
     return jsonConvert.serialize(device); 
    } 

    // We receive a json object (not string) and decide 
    // based on the given properties whether we want to 
    // create an instance of Computer or Mobile. 
    deserialize(device: any): Device { 

     const jsonConvert: JsonConvert = new JsonConvert(); 

     // We need the try/catch because of deserialize inside 
     try { 
     if (device.name && device.macAddress) { 
       const computer: Computer = new Computer(); 
       computer.name = device.name; 
       computer.macAddress = device.macAddress; 
       return jsonConvert.deserialize(computer, Computer); 
      } else if (device.name && device.number) 
       const mobile: Mobile = new Mobile(); 
       mobile.name = device.name; 
       mobile.number = device.number; 
       return jsonConvert.deserialize(mobile, Mobile); 
      } 
     } catch(e) {} 

     throw new TypeError(); 

    } 

} 

@JsonObject 
class JsonDevices { 
    @JsonProperty("devices", DeviceConverter) 
    devices: Device[] = []; 
} 

@JsonObject 
class Device { 
    @JsonProperty("name", String) 
    name: string = undefined; 
} 

@JsonObject 
class Mobile extends Device { 
    @JsonProperty("number", String) 
    number: string = undefined; 
} 

@JsonObject 
class Computer extends Device { 
    @JsonProperty("macAddress", String) 
    macAddress: string = undefined; 
} 

使用

// Assume this is your incoming json 
const jsonString: string = (" 
    [{ 
     'name':'mobile1', 
     'number':'600 600 600', 
     'class':'Mobile' 
    },{ 
     'name':'computer', 
     'macAddress:'123123123', 
     'class':'Computer' 
    }] 
"); 

// Convert it to an JSON/JavaScript object 
// In the current Angular 4 HttpClientModule API, 
// you would get an object directly and you wouldn't 
// bother with it anyway. 
const jsonArray: any[] = JSON.parse(jsonString); 

// Make sure the given array is added to an object 
// having a device array 
const jsonDevicesObject: any = { 
    devices: jsonArray; 
} 

// Now deserialize the whole thing with json2typescript: 
const jsonConvert: JsonConvert = new JsonConvert(); 
const jsonDevices: JsonDevices = jsonConvert.deserialize(jsonDevicesObject, JsonDevices); 

// Now all elements of jsonDevices.devices are of instance Mobile or Computer 
+0

使用'Mobile | Computer'而不是'Device'作爲提示可能會更聰明(甚至是必要的)? – andreas