web-dev-qa-db-fra.com

Comment analyser un objet JSON en un objet TypeScript

J'essaie actuellement de convertir mon objet JSON reçu en une classe TypeScript avec les mêmes attributs. Je ne parviens pas à le faire fonctionner. Qu'est-ce que je fais mal?

Classe d'employé

export class Employee{
    firstname: string;
    lastname: string;
    birthdate: Date;
    maxWorkHours: number;
    department: string;
    permissions: string;
    typeOfEmployee: string;
    note: string;
    lastUpdate: Date;
}

Chaîne d'employé

{
    "department": "<anystring>",
    "typeOfEmployee": "<anystring>",
    "firstname": "<anystring>",
    "lastname": "<anystring>",
    "birthdate": "<anydate>",
    "maxWorkHours": <anynumber>,
    "username": "<anystring>",
    "permissions": "<anystring>",
    "lastUpdate": "<anydate>"
    //I will add note later
}

Ma tentative

let e: Employee = new Employee();

Object.assign(e, {
    "department": "<anystring>",
    "typeOfEmployee": "<anystring>",
    "firstname": "<anystring>",
    "lastname": "<anystring>",
    "birthdate": "<anydate>",
    "maxWorkHours": 3,
    "username": "<anystring>",
    "permissions": "<anystring>",
    "lastUpdate": "<anydate>"
});

console.log(e);

Lien vers le TypeScript Playground

32
moessi774

La raison pour laquelle le compilateur vous permet de convertir l'objet renvoyé de JSON.parse vers une classe est due à TypeScript est basé sur un sous-typage structurel .
Vous n'avez pas vraiment d'instance de Employee, vous avez un objet (comme vous le voyez dans la console) qui a les mêmes propriétés.

Un exemple plus simple:

class A {
    constructor(public str: string, public num: number) {}
}

function logA(a: A) {
    console.log(`A instance with str: "${ a.str }" and num: ${ a.num }`);
}

let a1 = { str: "string", num: 0, boo: true };
let a2 = new A("stirng", 0);
logA(a1); // no errors
logA(a2);

( code dans la cour de récréation )

Il n'y a pas d'erreur car a1 satisfait le type A car il a toutes ses propriétés et la fonction logA peut être appelée sans erreur d'exécution même si ce qu'il reçoit n'est pas une instance de A tant qu'il a les mêmes propriétés.

Cela fonctionne très bien lorsque vos classes sont de simples objets de données et qu’elles n’ont aucune méthode, mais lorsque vous introduisez des méthodes, les choses ont tendance à casser:

class A {
    constructor(public str: string, public num: number) { }

    multiplyBy(x: number): number {
        return this.num * x;
    }
}

// this won't compile:
let a1 = { str: "string", num: 0, boo: true } as A; // Error: Type '{ str: string; num: number; boo: boolean; }' cannot be converted to type 'A'

// but this will:
let a2 = { str: "string", num: 0 } as A;

// and then you get a runtime error:
a2.multiplyBy(4); // Error: Uncaught TypeError: a2.multiplyBy is not a function

( code dans la cour de récréation )


Modifier

Cela fonctionne très bien:

const employeeString = '{"department":"<anystring>","typeOfEmployee":"<anystring>","firstname":"<anystring>","lastname":"<anystring>","birthdate":"<anydate>","maxWorkHours":0,"username":"<anystring>","permissions":"<anystring>","lastUpdate":"<anydate>"}';
let employee1 = JSON.parse(employeeString);
console.log(employee1);

( code dans la cour de récréation )

Si vous essayez d'utiliser JSON.parse sur votre objet alors que ce n'est pas une chaîne:

let e = {
    "department": "<anystring>",
    "typeOfEmployee": "<anystring>",
    "firstname": "<anystring>",
    "lastname": "<anystring>",
    "birthdate": "<anydate>",
    "maxWorkHours": 3,
    "username": "<anystring>",
    "permissions": "<anystring>",
    "lastUpdate": "<anydate>"
}
let employee2 = JSON.parse(e);

Vous obtiendrez alors le message d'erreur car ce n'est pas une chaîne, mais un objet. Si vous l'avez déjà sous cette forme, vous n'avez pas besoin d'utiliser JSON.parse.

Mais, comme je l'ai écrit, si vous utilisez cette méthode, vous ne disposerez pas d'une instance de la classe, mais simplement d'un objet possédant les mêmes propriétés que les membres de la classe.

Si vous voulez une instance, alors:

let e = new Employee();
Object.assign(e, {
    "department": "<anystring>",
    "typeOfEmployee": "<anystring>",
    "firstname": "<anystring>",
    "lastname": "<anystring>",
    "birthdate": "<anydate>",
    "maxWorkHours": 3,
    "username": "<anystring>",
    "permissions": "<anystring>",
    "lastUpdate": "<anydate>"
});
28
Nitzan Tomer

Si vous utilisez une interface TypeScript au lieu d'une classe , les choses sont plus simples:

export interface Employee {
    typeOfEmployee_id: number;
    department_id: number;
    permissions_id: number;
    maxWorkHours: number;
    employee_id: number;
    firstname: string;
    lastname: string;
    username: string;
    birthdate: Date;
    lastUpdate: Date;
}

let jsonObj: any = JSON.parse(employeeString); // string to generic object first
let employee: Employee = <Employee>jsonObj;

Si vous voulez une classe , le casting simple ne fonctionnera pas. Par exemple:

class Foo {
    name: string;
    public pump() { }
}

let jsonObj: any = JSON.parse('{ "name":"hello" }');
let fObj: Foo = <Foo>jsonObj;
fObj.pump(); // crash, method is undefined!

Pour une classe, vous devez écrire un constructeur qui accepte une chaîne/un objet JSON, puis parcourir les propriétés pour attribuer chaque membre manuellement, comme ceci:

class Foo {
    name: string;

    constructor(jsonStr: string) {
        let jsonObj: any = JSON.parse(jsonStr);
        for (let prop in jsonObj) {
            this[prop] = jsonObj[prop];
        }
    }
}

let fObj: Foo = new Foo(theJsonString);
31
Rodrigo

Vos données JSON ont des propriétés que vous n'avez pas dans votre classe. Pour le mappage Vous pouvez faire un mappage personnalisé simple

export class Employe{ ////
    static parse(json: string) {
           var data = JSON.parse(json);
            return new Employe(data.typeOfEmployee_id, data.firstName.. and others);
       }

}

et spécifiant également constructeur dans votre

Employé

classe

5
let employee = <Employee>JSON.parse(employeeString);

Rappelez-vous: Les typages forts sont uniquement au moment de la compilation car javascript ne le prend pas en charge.

4
Sefa

Tout d’abord, vous devez vous assurer que tous les attributs de ce service proviennent du même nom dans votre classe. Ensuite, vous pouvez analyser l'objet et ensuite l'assigner à votre nouvelle variable, quelque chose comme ceci:

const parsedJSON = JSON.parse(serverResponse);
const employeeObj: Employee = parsedJSON as Employee;

Essayez ça!