如何将JSON对象解析为TypeScript对象

问题描述 投票:23回答:5

我目前正在尝试将我收到的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);

Link to Typescript Playground

json angular typescript
5个回答
23
投票

编译器允许您将从JSON.parse返回的对象转换为类的原因是因为typescript is based on structural subtyping。 你没有真正的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);

(Qazxswpoi)

没有错误,因为code in playground满足类型a1,因为它具有所有属性,并且可以调用A函数而没有运行时错误,即使它接收的不是logA的实例,只要它具有相同的属性即可。

当你的类是简单的数据对象并且没有方法时,这很有用,但是一旦你引入了方法,那么事情往往会破坏:

A

(Qazxswpoi)


Edit

这很好用:

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

(Qazxswpoi)

如果您在对象上尝试使用code in playground时它不是字符串:

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 in playground了。

但是,正如我所写的那样,如果你采用这种方式,那么你将不会拥有该类的实例,只是一个与类成员具有相同属性的对象。

如果你想要一个实例,那么:

JSON.parse

28
投票

如果你使用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>"
});

对于类,您必须编写一个接受JSON字符串/对象的构造函数,然后遍历属性以手动分配每个成员,如下所示:

TypeScript interface

5
投票

您的JSON数据具有您在课堂上没有的一些属性。用于映射您可以执行简单的自定义映射

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;

并指定你的构造函数

雇员


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

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

请记住:强类型只是编译时间,因为javascript不支持它。


0
投票

首先,您需要确保来自服务的所有属性在您的类中命名相同。然后你可以解析对象,然后将它分配给你的新变量,如下所示:

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

试试吧!

© www.soinside.com 2019 - 2024. All rights reserved.