使用 TypeScript 解析复杂的 json 对象

Posted

技术标签:

【中文标题】使用 TypeScript 解析复杂的 json 对象【英文标题】:Parse complex json objects with TypeScript 【发布时间】: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 返回一个数字。

【问题讨论】:

【参考方案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;
    );

【讨论】:

以上是关于使用 TypeScript 解析复杂的 json 对象的主要内容,如果未能解决你的问题,请参考以下文章

将 json 解析为 typescript 中的接口并检查是不是正常

在 Typescript 中解析 JSON 对象

JSON解析期间的Typescript自动类型转换?

在 Angular 应用程序中将 JSON 解析为 Typescript 类

带有 TypeScript 解析器/插件的 ESLint:如何包含从 tsconfig.json 中排除的 .spec.ts?

在 Typescript 中解析 JSON 数组