Citrus
Citrus

Reputation: 766

Convert JSON to object type in Angular

I'm having real trouble converting a JSON array to collection of objects in Angular. I've not used Angular for some time, please forgive me if any of my terminology is incorrect.

I have the following products.json file in my project:

[
  {
    "id": 1,
    "name": "Pen",
    "description": "The finest blue pen.",
    "relatedProducts": [2]
  },
  {
    "id": 2,
    "name": "A4 Paper",
    "description": "A4 sized printer paper.",
    "relatedProducts": [1]
  }
]

This product.ts file:

export class Product {
    Id: number;
    Name: string;
    Description: string;
    RelatedProducts: Array<number>;
}

My app.component.ts file:

import * as ProductsJson from '../../json-data/products.json';
import { Component, OnInit } from '@angular/core';
import { Product } from 'src/app/models/product';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  productsJson: any = ProductsJson;
  products: Array<Product>;

  ngOnInit() {
    this.products = <Product[]>this.productsJson;
    console.log(this.products);
  }
}

And finally my app.component.html:

<ul>
  <li *ngFor="let p of products">
    {{p.Id}} {{p.Name}}
  </li>
</ul>

enter image description here

My console log shows the JSON data but it seems as though I'm making some error trying to convert it to a list of Product objects. This is also preventing me from successfully using ngFor in my view as the console error shows, so nothing shows on the page. How can I perform this conversion correctly so the loop works and this data is shown on the view?

Upvotes: 4

Views: 11620

Answers (8)

Krishneel Singh
Krishneel Singh

Reputation: 343

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
   selector: 'app-hello-world',
   templateUrl: './hello-world.component.html',
   styleUrls: ['./hello-world.component.css'],
})
export class HelloWorldComponent implements OnInit {
   jsonString: string = '[{"title":"test"},{"title":"test2"}]';
   jsonObj: Array<object>;
   jsonObj2: Array<object> = [{ title: 'test' }, { title: 'test2' }];
  constructor() {
     this.jsonObj = JSON.parse(this.jsonString);
     this.jsonString = JSON.stringify(this.jsonObj2);
  }

  ngOnInit() {}
}

Upvotes: 0

Gaurang Dhorda
Gaurang Dhorda

Reputation: 3387

UPDATE 1 [ You can go declarative way of rxjs too ]..

Use of operator of rxjs to create new stream of observable from your json file.

import {of} from 'rxjs'

productsJson = of <Product []>(ProductsJson);

export interface Product{
      id: number;
      name: string;
      description: string;
      relatedProducts: Array<number>;
}

and then in your template you can simply use async pipe ...

<ul>
  <li *ngFor="let p of productsJson | async">
    {{p.id}} {{p.name}}
  </li>
</ul>

Update 2 [ You can simply use JSON.parse() and JSON.stringify() ]..

 productsJson: any = JSON.parse(JSON.stringify(ProductsJson));

and then use this in template like this...

<div *ngFor = "let item of productsJson">
    <span> {{item.id }} </span>
</div>

Upvotes: 0

German Cosano
German Cosano

Reputation: 107

step by step:

Component.ts

The first, you have unuseless variables you have reduce keeping just one 'products' and initializing just like that the following code.

In ngOnInit() you must to load the array initialized before. The way to do that is casting with type any cause importing from local json generates another data model, you have to access to the property 'default' and that's all.

import * as ProductsJson from '../../json-data/products.json';
import { Component, OnInit } from '@angular/core';
import { Product } from 'src/app/models/product';

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

  products: Array<Product> = new Array<Product>();

  ngOnInit() {
    this.products = (ProductsJson as any).default;
    console.log(this.products);
  }

}

Component.html

Another point to change is properties naming you have 'Id' & 'Name' instead of 'id' and 'name'.

<ul>
   <li *ngFor="let p of products">
    {{p.id}} {{p.name}}
   </li>
</ul>

Entities

Product Class have to change the properties naming without Capital letters to have a correspondence with the Json Data or change Json data model to the Class anyway.

If I were you I will change also Product, using interface instead Class

export interface Product {
  id: number;
  name: string;
  description: string;
  relatedProducts: Array<number>;
}

Upvotes: 0

deelde
deelde

Reputation: 1591

you can use class-transformer which helps you to convert plain javascript objects to real es6 classes. With this real instances you can also use class methods.

import { Component, OnInit } from "@angular/core";
import ProductsJson from "./products.json";
import {plainToClass} from "class-transformer";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
  productsJson: any = ProductsJson;
  products: Array<Product>;
  constructor() {}
  ngOnInit() {
    //this.products = <Product[]>this.productsJson;
    this.products = plainToClass(Product, this.productsJson as []);
    console.log(this.products);
  }
}
export class Product {
  id: number;
  name: string;
  description: string;
  relatedProducts: Array<number>;

  getId(){
    return this.id + "_ID";
  }
}

template:

<ul>
    <li *ngFor="let p of products">
        {{p.getId()}} {{p.id}} {{p.name}}
    </li>
</ul>

Upvotes: 2

Om Dhanwant
Om Dhanwant

Reputation: 51

**- Use interface instead of class for Product.**

      export interface Product {
        id: number;
        name: string;
        description: string;
        relatedProducts: number[];
    }

**- If you need a class, then specify the parameterised constructor to assign variable values.**

  export class Product {
    id: number;
    name: string;
    description: string;
    relatedProducts: number[];

  constructor(product) {
     this.id = product.id;
    this.name: product.name;
    this.description: product.description;
    this.relatedProducts: product.relatedProducts;
   }
}


**and then inside the component you can use** 

this.products = new Product(this.productsJson); // if Product is a class

OR

this.products = this.productsJson; // if Product is an interface

Upvotes: 2

Sivuyile TG Magutywa
Sivuyile TG Magutywa

Reputation: 1271

Adding to Kushal Shah answer this also works.

import { Component, OnInit } from "@angular/core";
import ProductsJson from "./products.json";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {

  products = <Product[]>ProductsJson;;

  constructor() {}

  ngOnInit() {
    console.log(this.products);
  }

}

export class Product {
  id: number;
  name: string;
  description: string;
  relatedProducts: Array<number>;
}

Upvotes: 0

kushal shah
kushal shah

Reputation: 863

look at stackblitz

Let me know still you have an issue..

thanks

Upvotes: 2

Sajeetharan
Sajeetharan

Reputation: 222722

Your model should look like below,

export interface Product {
    id: number;
    name: string;
    description: string;
    relatedProducts: number[];
}

Change the products as

 products: Product[];

and then,

this.products = this.productsJson;

Upvotes: 0

Related Questions