yesman
yesman

Reputation: 7838

Parse array of JSON objects to array of TypeScript objects

I have an endpoint that returns this Json:

{
  "result": [
    {
      "id": 1,
      "name": "Kayak",
      "category": "Watersports",
      "description": "A boat for one person",
      "price": 27500,
      "currencyCode": "EUR"
    },
    {
      "id": 2,
      "name": "Lifejacket",
      "category": "Watersports",
      "description": "Protective and fashionable",
      "price": 48095,
      "currencyCode": "EUR"
    },
    {
      "id": 3,
      "name": "Soccer Ball",
      "category": "Soccer",
      "description": "FIFA-approved size and weight",
      "price": 1950,
      "currencyCode": "EUR"
    }
]
}

I have a class called Product in Angular:

import { Money, Currencies } from 'ts-money';

export class Product {
private money: Money;
public Amount = this.money.amount;

public constructor(
    public Id: number,
    public Name: string,
    public Category: string,
    public Price: number,
    public Description: string,
    public CurrencyCode: string) {
        this.money = new Money(Price, CurrencyCode);
    }

public GetPrice(): Money {
    return this.money;
}
}

I made this code in Angular:

export class ProductComponent implements OnInit {

  constructor(private datasource: ProductDataSource) {
  }

  private products: Product[];

  ngOnInit(): void {
    this.datasource.GetProducts()
    .subscribe((data) => {
        this.products = data;
    });
  }
 }
}

This code successfully returns an array of JSON objects that have the same properties as Product. Now, when I subscribe to this observable:

this.datasource.GetProducts()
.subscribe((data) => {
    // this.products is a class property of type Product[]
    this.products = data; // How do I make this work?
});

I can not figure out how to make the transition from JSON object to Angular class. My HTML page does not recognize this.products as an array of Product objects. What do I do?

Upvotes: 1

Views: 434

Answers (5)

Mujadid Mughal
Mujadid Mughal

Reputation: 2663

Another approach could be to make JSON data, compatible with your Product class. You could use the map rxjs operator to transform your JSON data into Product. Modify the get products code, like this

    const source$ = of(result).pipe(pluck('result'),map(item=> item.map(x=>{
      let product = new Product(x.id,x.name, x.category, x.price, x.description, x.currencyCode);
      return product;
    })));

Here is a StackBlitz link.

Upvotes: 2

uiTeam324
uiTeam324

Reputation: 1245

Change class to interface and change the case of also.

export interface Product{

public id: number;
public name: string;
public category: string;
public price: number;
public description: string;
public currencyCode: string; }

Upvotes: 0

raharshi puli
raharshi puli

Reputation: 326

create product interface with variables and use that interface to create array

    export interface Product{
      public Id: number,
      public Name: string,
      public Category: string,
      public Price: number,
      public Description: string,
      public CurrencyCode: string
    }

     products:Product[];

Upvotes: 0

Alann
Alann

Reputation: 657

I think it's because of your mapping in your product class and also the type of your class, try to change class Product to interface Product

like this

    export interface Product{

    public id: number;
    public name: string;
    public category: string;
    public price: number;
    public description: string;
    public currencyCode: string; 

 }

you can go take a look at Angular : Class and Interface for the differences between class and interface

EDIT : (as you can see in my code, I also changed the variable name to match with your JSON response)

Upvotes: 4

qiAlex
qiAlex

Reputation: 4356

Product properties names and json properties names doesn't match. You can do it like this:

this.datasource.GetProducts()
  .subscribe((data) => {
    // this.products is a class property of type Product[]
    this.products = (data || []).map(item => new Product(item.id, item.name, item.category, item.price, item.description, item.currencyCode))
  });

Upvotes: 1

Related Questions