Reputation: 9391
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.
Upvotes: 12
Views: 15582
Reputation: 1530
You could use the rxjs's map operator to manually map the entities in you DataService
.
I haven't tested the code, so it may be that you'll need to map the invoices as well with rx (invoices.map( ... )) to iterate the collection, but the principle remains the same.
getCustomer(id: number): Observable<Customer> {
return this.http.get<Customer>(this.customerUrl).map(customer => {
let newCustomer = customer;
newCustomer.invoices = customer.invoices;
return newCustomer;
});
}
Upvotes: 0
Reputation: 32022
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;
Upvotes: 11