web-dev-qa-db-ja.com

JSONオブジェクトをTypeScriptオブジェクトに解析する方法

現在、受け取ったJSONオブジェクトを同じ属性を持つTypeScriptクラスに変換しようとしていますが、動作させることができません。私は何を間違えていますか?

従業員クラス

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

従業員文字列

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

私の試み

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

TypeScriptプレイグラウンドへのリンク

32
moessi774

コンパイラがJSON.parseから返されたオブジェクトをクラスにキャストできる理由は、 TypeScriptは構造サブタイプに基づいている であるためです。
実際にはEmployeeのインスタンスはなく、同じプロパティを持つオブジェクト(コンソールに表示される)があります。

より簡単な例:

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

遊び場のコード

a1はすべてのプロパティを持っているためA型を満たすため、エラーはありません。また、logA関数は、受け取ったものがインスタンスでなくても実行時エラーなしで呼び出すことができます。 A同じプロパティがある限り。

クラスが単純なデータオブジェクトであり、メソッドを持たない場合はうまく機能しますが、メソッドを導入すると問題が発生する傾向があります。

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

遊び場のコード


編集

これはうまく機能します:

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

遊び場のコード

オブジェクトが文字列ではないときにJSON.parseを使用しようとしている場合:

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

それは文字列ではなく、オブジェクトであるため、エラーが発生します。すでにこのフォームにある場合は、JSON.parseを使用する必要はありません。

しかし、私が書いたように、あなたがこの方法で進んでいる場合、クラスのインスタンスはなく、クラスのメンバーと同じプロパティを持つオブジェクトだけがあります。

インスタンスが必要な場合:

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

classの代わりに TypeScriptinterface を使用すると、状況はより簡単になります。

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;

ただし、classが必要な場合、単純なキャストは機能しません。例えば:

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

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

クラスの場合、JSON文字列/オブジェクトを受け入れるコンストラクターを作成し、次のようにプロパティを反復処理して各メンバーを手動で割り当てる必要があります。

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

JSONデータには、クラスにはないプロパティがいくつかあります。マッピングの場合簡単なカスタムマッピングを行うことができます

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

}

また、

社員

クラス

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

要確認:強力な型指定は、javascriptでサポートされていないため、コンパイル時のみです。

4
Sefa

まず、サービスから取得されるすべての属性に、クラス内で同じ名前が付けられていることを確認する必要があります。次に、オブジェクトを解析し、その後、次のような新しい変数にオブジェクトを割り当てます。

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

やってみて!