Json为打字稿对象。继承

Json为打字稿对象。继承

问题描述:

我有三个类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

我根据我的解决方案是什么安德烈亚斯写道:谢谢。 为了达到正确的解决方案,我使用了令人敬畏的库 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); 

非常感谢你:)

我建议以下实现。请注意里面的意见。它可能包含一些错误,因为我实际上无法检查代码,所以可能需要做更多的工作。

基本思路:为了使组件中的代码变得简单,您应该将数组包装到一个对象中,这里称为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