【问题标题】:Parse complex json objects with TypeScript使用 TypeScript 解析复杂的 json 对象
【发布时间】:2016-05-31 20:54:51
【问题描述】:

如何使用 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 返回一个数字。

【问题讨论】:

    标签: json typescript angular


    【解决方案1】:

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

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

    您可以创建一个接口声明,使用它您可以执行type-assertion(不是类型-cast)以在某种程度上模仿类型安全如果 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;
    

    【讨论】:

    • 在 Angular 5 中甚至无法导入。
    • @Shoaib Angular 是一个框架,而不是一种语言,它不会改变您导入模块的方式。
    【解决方案2】:

    您可以使用 rxjs 的 map 运算符手动映射您 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;
        });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-22
      • 2019-07-11
      • 2015-09-05
      • 1970-01-01
      • 1970-01-01
      • 2011-06-01
      相关资源
      最近更新 更多