[英]How to parse a JSON object to a TypeScript Object
我目前正在尝试将收到的 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接口而不是class ,事情就更简单了:
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);
编译器允许您将从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>"
});
let employee = <Employee>JSON.parse(employeeString);
记住:强类型只是编译时间,因为 javascript 不支持它。
您的 JSON 数据可能具有您的类中没有的一些属性。 对于映射您可以进行简单的自定义映射
export class Employe{ ////
static parse(json: string) {
var data = JSON.parse(json);
return new Employe(data.typeOfEmployee_id, data.firstName.. and others);
}
}
并在您的Employee
类中指定构造函数。
我喜欢使用一个名为class-transformer的小库。
它可以处理嵌套对象,将字符串映射到日期对象并处理更多不同的 json-property-names。
也许值得一看。
import { Type, plainToClass, Expose } from "class-transformer";
import 'reflect-metadata';
export class Employee{
@Expose({ name: "uid" })
id: number;
firstname: string;
lastname: string;
birthdate: Date;
maxWorkHours: number;
department: string;
@Type(() => Permission)
permissions: Permission[] = [];
typeOfEmployee: string;
note: string;
@Type(() => Date)
lastUpdate: Date;
}
export class Permission {
type : string;
}
let json:string = {
"uid": 123,
"department": "<anystring>",
"typeOfEmployee": "<anystring>",
"firstname": "<anystring>",
"lastname": "<anystring>",
"birthdate": "<anydate>",
"maxWorkHours": 1,
"username": "<anystring>",
"permissions": [
{'type' : 'read'},
{'type' : 'write'}
],
"lastUpdate": "2020-05-08"
}
console.log(plainToClass(Employee, json));
```
首先,您需要确保来自服务的所有属性在您的类中命名相同。 然后您可以解析该对象,然后将其分配给您的新变量,如下所示:
const parsedJSON = JSON.parse(serverResponse);
const employeeObj: Employee = parsedJSON as Employee;
试试看!
尝试在您的类中使用构造函数过程。
对象.assign
是一把钥匙
请看一下这个样本:
class Employee{
firstname: string;
lastname: string;
birthdate: Date;
maxWorkHours: number;
department: string;
permissions: string;
typeOfEmployee: string;
note: string;
lastUpdate: Date;
constructor(original: Object) {
Object.assign(this, original);
}
}
let e = new Employee({
"department": "<anystring>",
"typeOfEmployee": "<anystring>",
"firstname": "<anystring>",
"lastname": "<anystring>",
"birthdate": "<anydate>",
"maxWorkHours": 3,
"username": "<anystring>",
"permissions": "<anystring>",
"lastUpdate": "<anydate>"
});
console.log(e);
您可以按如下方式转换 json:
鉴于您的课程:
export class Employee{
firstname: string= '';
}
和json:
let jsonObj = {
"firstname": "Hesham"
};
您可以按如下方式进行转换:
let e: Employee = jsonObj as Employee;
以及console.log(e);
是:
{名字:'Hesham'}
您可以为您的类创建一个新对象,然后从 JSON 对象的参数动态分配它的参数。
const employeeData = JSON.parse(employeeString);
let emp:Employee=new Employee();
const keys=Object.keys(employeeData);
keys.forEach(key=>{
emp[key]=employeeData[key];
});
console.log(emp);
现在emp是Employee的一个对象,包含employeeString的Json对象(employeeData)的所有字段;
您可以使用语法“as”执行此操作吗?
async getProfile(): Promise<Contact> {
const url: string = this.baseApi;
const response = await this.http.get(url).toPromise()
return JSON.parse(response.json()) as Contact;
}
if it is coming from server as object you can do
this.service.subscribe(data:any) 保留任何类型的数据将解决问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.