Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse complex json objects with TypeScript

How can I parse complex json object with TypeScipt ?

I have a customer object, who have some invoices.

This is my model :

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() {
     }
}

And in my service I have :

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

Customer data are great (my customer id, name etc have some values) but the invoices are null.

The json is correct, data.Invoices.length return a number.

like image 200
AdrienTorris Avatar asked Feb 19 '16 10:02

AdrienTorris


People also ask

How do you create a type for a complex JSON object in TypeScript?

After TypeScript 3.7 we can also define it in a confined way: type JSONValue = | string | number | boolean | { [x: string]: JSONValue } | Array<JSONValue>; JSONValue circularly references itself. Happy coding!

How do I Stringify a JSON object in TypeScript?

Stringify a JavaScript ObjectUse the JavaScript function JSON.stringify() to convert it into a string. const myJSON = JSON.stringify(obj); The result will be a string following the JSON notation.


1 Answers

How can I parse complex json object with TypeScipt ?

Assuming you mean parsing JSON into actual class instances instead of simple Javascript objects, TypeScript does not ship this feature off-the-shelf.

You may create an interface declaration using which you can do a type-assertion (not a type-cast) to somewhat mimick type-safety if the JSON is trusted, but that's it -- I know no native tool to serialize a JSON to actual instances of user-defined types.

interface ICustomerInvoice {
    id: number;
}

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

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

Nevertheless, for the same obvious reasons I began putting together TypedJSON to introduce this feature into TypeScript. You can annotate your classes and members with JsonObject and JsonMember decorators:

@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;
    }
}

To deserialize a JSON-string, you would use TypedJSON.parse instead of JSON.parse, the getter will also be present as expected:

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

It is recommended to be used with ReflectDecorators (but not required). If you choose to skip this recommendation, you also need to specify the 'type' setting for members, for example:

@JsonMember({ type: String })
public id: string;
like image 176
John Weisz Avatar answered Sep 23 '22 05:09

John Weisz