使用TypeScript解析复杂的json对象

时间:2016-02-19 10:14:01

标签: json typescript angular

如何使用TypeScipt解析复杂的json对象?

我有一个客户对象,他有一些发票。

这是我的模特:

export class Customer {
    public id: string;
    public name: string;
    public invoices: CustomerInvoice[];

    get invoicesCount(): number {
        if (this.invoices== null) {
            return 0;
        }
        return this.invoices.length;
    }

     constructor() {
     }
}

export class CustomerInvoice {
     public id: number;

     constructor() {
     }
}

在我的服务中,我有:

ngOnInit() {
    if (this.id != null) {
        this.dataService.getCustomer(this.id).subscribe(data => {
            this.customer = data;
        },
            err => console.log(err));
    }
}

客户数据很棒(我的客户ID,名称等都有一些值)但发票是空的。

json是正确的,data.Invoices.length返回一个数字。

2 个答案:

答案 0 :(得分:8)

  

如何使用TypeScipt解析复杂的json对象?

假设您的意思是将JSON解析为实际的类实例而不是简单的Javascript对象,TypeScript不提供此功能现成的

您可以创建一个接口声明,使用该接口声明可以执行type-assertion(而不是类型强制转换)来模仿类型安全性如果 JSON是可信的,但就是这样 - 我不知道将JSON序列化为用户定义类型的实际实例的原生工具。

interface ICustomerInvoice {
    id: number;
}

interface ICustomer {
    id: string;
    name: string;
    invoices: ICustomerInvoice[];
}

var customer: ICustomer = JSON.parse(json) as ICustomer;

然而,出于同样显而易见的原因,我开始将TypedJSON放在一起将此功能引入TypeScript。您可以使用JsonObject和JsonMember装饰器注释您的类和成员:

@JsonObject
export class CustomerInvoice {
    @JsonMember
    public id: number;
}

@JsonObject
export class Customer {
    @JsonMember
    public id: string;

    @JsonMember
    public name: string;

    @JsonMember({ elementType: CustomerInvoice })
    public invoices: CustomerInvoice[];

    get invoicesCount(): number {
        if (this.invoices== null) {
            return 0;
        }
        return this.invoices.length;
    }
}

要反序列化JSON字符串,您可以使用TypedJSON.parse而不是JSON.parse,getter也将按预期显示:

var customer = TypedJSON.parse(json, Customer);
typeof customer.invoicesCount; // "number"    

推荐ReflectDecorators一起使用(但不是必需的)。如果您选择跳过此建议,则还需要为成员指定“类型”设置,例如:

@JsonMember({ type: String })
public id: string;

答案 1 :(得分:0)

您可以使用rxjs的地图运算符手动映射您DataService中的实体。

我还没有测试过代码,因此您可能需要使用rx(invoices.map(...))来映射发票以迭代集合,但原则仍然相同。

getCustomer(id: number): Observable<Customer> {
    return this.http.get<Customer>(this.customerUrl).map(customer => {
        let newCustomer = customer;

        newCustomer.invoices = customer.invoices;

        return newCustomer;
    });
}