serialisering - Typescript deserialisering av json til samling med flere typer


Jeg bruker TypeScript for et prosjekt og trenger å serialisere en samling til JSON, lagre det i en fil og senere deserialisere den filen til en lignende samling. Samlingen ser omtrent slik ut:

elements: Array<tool>

og mitt verktøygrensesnitt ser slik ut:

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

og en verktøyimplementering ville se slik ut:

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

Jeg har noen få implementasjoner av verktøygrensesnittet: textTool, imageTool og rectangleTool. Problemet jeg trenger å løse er at når jeg deserialiserer filinnholdet til en samling av verktøy, får jeg bare et vanlig objekt og ikke en instans av for eksempel textTool.

Jeg bruker JSON.stringify(elements) for å lage en json og JSON.parse(jsonText) for å deserialisere.

Jeg forstår at parseren ikke har noe måte å vite hvilken type den skal opprette en instans av, gitt at json-teksten ikke har informasjon om det. Jeg tenkte å legge til et felt eller noe for å identifisere hvilken klasseinstans jeg trenger og manuelt 'new' den klassen. Finnes det noen alternativer der jeg ikke trenger å manuelt parse json til en samling av verktøy (med riktige typer)?

Svar #1

Som du sa, kan du legge til et felt type, opprette en kobling mellom type-streng og implementeringsklasse, og deretter vil konverteringskoden være ganske enkel:

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;
});

* Kloning av kode er veldig enkel, men den er god nok for vanlige objekter.

Svar #2

for enkle objekter, prøv dette:

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

og kall det:

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

Relaterte artikler