如何将 JSON 对象解析为 TypeScript 对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40421100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to parse a JSON object to a TypeScript Object
提问by moessi774
I am currently trying to convert my received JSON Object into a TypeScript class with the same attributes and I cannot get it to work. What am I doing wrong?
我目前正在尝试将我收到的 JSON 对象转换为具有相同属性的 TypeScript 类,但我无法让它工作。我究竟做错了什么?
Employee Class
员工班
export class Employee{
firstname: string;
lastname: string;
birthdate: Date;
maxWorkHours: number;
department: string;
permissions: string;
typeOfEmployee: string;
note: string;
lastUpdate: Date;
}
Employee String
员工字符串
{
"department": "<anystring>",
"typeOfEmployee": "<anystring>",
"firstname": "<anystring>",
"lastname": "<anystring>",
"birthdate": "<anydate>",
"maxWorkHours": <anynumber>,
"username": "<anystring>",
"permissions": "<anystring>",
"lastUpdate": "<anydate>"
//I will add note later
}
My Attempt
我的尝试
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);
采纳答案by Nitzan Tomer
The reason that the compiler lets you cast the object returned from JSON.parseto a class is because typescript is based on structural subtyping.
You don't really have an instance of an Employee, you have an object (as you see in the console) which has the same properties.
编译器允许您将返回的对象JSON.parse转换为类的原因是因为typescript 基于结构子类型。
您实际上没有 an 的实例Employee,您有一个具有相同属性的对象(如您在控制台中看到的)。
A simpler example:
一个更简单的例子:
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);
(操场上的代码)
There's no error because a1satisfies type Abecause it has all of its properties, and the logAfunction can be called with no runtime errors even if what it receives isn't an instance of Aas long as it has the same properties.
没有错误,因为a1满足类型,A因为它具有它的所有属性,并且该logA函数可以在没有运行时错误的情况下被调用,即使它收到的不是实例,A只要它具有相同的属性。
That works great when your classes are simple data objects and have no methods, but once you introduce methods then things tend to break:
当你的类是简单的数据对象并且没有方法时,这很有效,但是一旦你引入了方法,事情就会变得很糟糕:
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
(操场上的代码)
Edit
编辑
This works just fine:
这工作得很好:
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);
(操场上的代码)
If you're trying to use JSON.parseon your object when it's not a string:
如果您尝试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);
Then you'll get the error because it's not a string, it's an object, and if you already have it in this form then there's no need to use JSON.parse.
然后你会得到错误,因为它不是一个字符串,它是一个对象,如果你已经以这种形式拥有它,那么就不需要使用JSON.parse.
But, as I wrote, if you're going with this way then you won't have an instance of the class, just an object that has the same properties as the class members.
但是,正如我所写的,如果你采用这种方式,那么你将没有类的实例,只有一个与类成员具有相同属性的对象。
If you want an instance then:
如果你想要一个实例,那么:
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>"
});
回答by Rodrigo
If you use a TypeScript interfaceinstead of a class, things are simpler:
如果您使用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;
If you want a class, however, simple casting won't work. For example:
但是,如果您想要一个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!
For a class, you'll have to write a constructor which accepts a JSON string/object and then iterate through the properties to assign each member manually, like this:
对于类,您必须编写一个接受 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);
回答by Alexandr Sargsyan
Your JSON data have some properties that you have not in your class. For mapping You can do simple custom mapping
您的 JSON 数据具有一些您的类中没有的属性。对于映射您可以进行简单的自定义映射
export class Employe{ ////
static parse(json: string) {
var data = JSON.parse(json);
return new Employe(data.typeOfEmployee_id, data.firstName.. and others);
}
}
and also specifying constructor in your
并在您的
Employee
员工
class
班级
回答by Sefa
let employee = <Employee>JSON.parse(employeeString);
Remember: Strong typings is compile time only since javascript doesn't support it.
请记住:强类型只是编译时,因为 javascript 不支持它。
回答by Juan Carlos Vega Abarca
First of all you need to be sure that all attributes of that comes from the service are named the same in your class. Then you can parse the object and after that assign it to your new variable, something like this:
首先,您需要确保来自服务的所有属性在您的类中都具有相同的名称。然后您可以解析该对象,然后将其分配给您的新变量,如下所示:
const parsedJSON = JSON.parse(serverResponse);
const employeeObj: Employee = parsedJSON as Employee;
Try that!
试试吧!
回答by Vlad
Try to use constructor procedure in your class.
尝试在您的类中使用构造函数过程。
Object.assign
对象分配
is a key
是一把钥匙
Please take a look on this sample:
请看一下这个样本:
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);
回答by deelde
i like to use a littly tiny library called class-transformer.
我喜欢使用一个名为class-transformer 的小库。
it can handle nested-objects, map strings to date-objects and handle different json-property-names a lot more.
它可以处理嵌套对象,将字符串映射到日期对象并处理更多不同的 json-property-names。
Maybe worth a look.
也许值得一看。
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));
```

