我从对REST服务器的AJAX调用中接收到一个JSON对象。这个对象的属性名与我的TypeScript类相匹配(这是这个问题的后续)。
初始化它的最佳方法是什么?我不认为这将工作,因为类(& JSON对象)的成员是对象的列表和成员是类,而这些类的成员是列表和/或类。
但我更喜欢一种方法,查找成员名和分配他们,创建列表和实例化类的需要,所以我不必为每个类中的每个成员写显式代码(有很多!)
我从对REST服务器的AJAX调用中接收到一个JSON对象。这个对象的属性名与我的TypeScript类相匹配(这是这个问题的后续)。
初始化它的最佳方法是什么?我不认为这将工作,因为类(& JSON对象)的成员是对象的列表和成员是类,而这些类的成员是列表和/或类。
但我更喜欢一种方法,查找成员名和分配他们,创建列表和实例化类的需要,所以我不必为每个类中的每个成员写显式代码(有很多!)
当前回答
我发现最适合这个目的的是类转换器
这就是它的用法:
一些类:
export class Foo {
name: string;
@Type(() => Bar)
bar: Bar;
public someFunction = (test: string): boolean => {
...
}
}
// the docs say "import [this shim] in a global place, like app.ts"
import 'reflect-metadata';
// import this function where you need to use it
import { plainToClass } from 'class-transformer';
export class SomeService {
anyFunction() {
u = plainToClass(Foo, JSONobj);
}
}
如果使用@Type装饰器,也会创建嵌套属性。
其他回答
选项#5:使用Typescript构造函数和jQuery.extend
这似乎是最可维护的方法:添加一个以json结构作为参数的构造函数,并扩展json对象。这样就可以将json结构解析为整个应用程序模型。
不需要创建接口,或者在构造函数中列出属性。
export class Company
{
Employees : Employee[];
constructor( jsonData: any )
{
jQuery.extend( this, jsonData);
// apply the same principle to linked objects:
if ( jsonData.Employees )
this.Employees = jQuery.map( jsonData.Employees , (emp) => {
return new Employee ( emp ); });
}
calculateSalaries() : void { .... }
}
export class Employee
{
name: string;
salary: number;
city: string;
constructor( jsonData: any )
{
jQuery.extend( this, jsonData);
// case where your object's property does not match the json's:
this.city = jsonData.town;
}
}
在你的ajax回调中,你收到一个公司来计算工资:
onReceiveCompany( jsonCompany : any )
{
let newCompany = new Company( jsonCompany );
// call the methods on your newCompany object ...
newCompany.calculateSalaries()
}
也许不现实,但简单的解决方案:
interface Bar{
x:number;
y?:string;
}
var baz:Bar = JSON.parse(jsonString);
alert(baz.y);
对困难的依赖也要努力!!
**model.ts**
export class Item {
private key: JSON;
constructor(jsonItem: any) {
this.key = jsonItem;
}
}
**service.ts**
import { Item } from '../model/items';
export class ItemService {
items: Item;
constructor() {
this.items = new Item({
'logo': 'Logo',
'home': 'Home',
'about': 'About',
'contact': 'Contact',
});
}
getItems(): Item {
return this.items;
}
}
这是我的方法(非常简单):
const jsonObj: { [key: string]: any } = JSON.parse(jsonStr);
for (const key in jsonObj) {
if (!jsonObj.hasOwnProperty(key)) {
continue;
}
console.log(key); // Key
console.log(jsonObj[key]); // Value
// Your logic...
}
我一直在用这个家伙来做这项工作:https://github.com/weichx/cerialize
它非常简单,但功能强大。它支持:
整个对象树的序列化和反序列化。 同一对象上的持久和瞬态属性。 用于自定义(反)序列化逻辑的钩子。 它可以(反)序列化到一个现有的实例中(这对Angular来说很棒),也可以生成新的实例。 等。
例子:
class Tree {
@deserialize public species : string;
@deserializeAs(Leaf) public leafs : Array<Leaf>; //arrays do not need extra specifications, just a type.
@deserializeAs(Bark, 'barkType') public bark : Bark; //using custom type and custom key name
@deserializeIndexable(Leaf) public leafMap : {[idx : string] : Leaf}; //use an object as a map
}
class Leaf {
@deserialize public color : string;
@deserialize public blooming : boolean;
@deserializeAs(Date) public bloomedAt : Date;
}
class Bark {
@deserialize roughness : number;
}
var json = {
species: 'Oak',
barkType: { roughness: 1 },
leafs: [ {color: 'red', blooming: false, bloomedAt: 'Mon Dec 07 2015 11:48:20 GMT-0500 (EST)' } ],
leafMap: { type1: { some leaf data }, type2: { some leaf data } }
}
var tree: Tree = Deserialize(json, Tree);