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