Typescript deserializing json into collection with multiple types

情到浓时终转凉″ 提交于 2020-01-20 08:21:49

问题


I'm using typescript for a project and need to serialize a collection to json, save it to a file and later deserialize that file into a similar collection. The collection looks something like:

elements: Array<tool>

and my tool interface looks like:

export interface tool {
    name: string;
    draw(context:any);
}

and a tool implementation would look like:

export class textTool implements tool {
    name: string;
    fontSize:number;
    fontType:string;
    draw(context:any){
        // draws the control...
    }
}

I have few implementations of tool interface: textTool, imageTool and rectangleTool. The problem I need to solve is that when I deserialize the file content into a collection of tool I get just a regular object and not an instance of textTool for example.

I'm using JSON.stringify(elements) to create a json and JSON.parse(jsonText) to deserialize.

I understand that the parser has no way to know which type it should create an instance of given the json text has no information about it. I thought of adding a field or something to identify which class instance I need and manually 'new' that class. Any options where I don't need to manually parse the json to collection of tool (with proper types)?


回答1:


As you said you can add a field type, create a mapping between type-string to implementation-class and then conversion code will be pretty straight forward:

export interface tool {
    type: string;
    name: string;
    draw(context:any): void;
}

class textTool implements tool {
    type:string = 'textTool';
    name:string;
    fontSize:number;
    fontType:string;

    draw(context:any):void {
    }
}

const typeMapping:any = {
    'textTool' : textTool
    //all other types
};
let json = '[{"type":"textTool", "name": "someName", "fontSize": 11}]';
let elements: Array<tool> = JSON.parse(json).map((i:any) => {
    let target:any = new typeMapping[i.type];
    for (const key in i) {
        target[key] = i[key];
    }
    return target;
});

* Cloning code is very simplistic, but it is good enough for plain objects.




回答2:


for plain objects try it:

function deserialize<T>(json): T[] {
    let collection: T[] = [];
    json.map((item: T) => {
        collection.push(item);
    });
    return collection;
}

and call it:

let tools: tool[] = deserialize<textTool>(json);


来源:https://stackoverflow.com/questions/38100853/typescript-deserializing-json-into-collection-with-multiple-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!