Retrieve JSON Data In Angular 5 - json

I am retrieving json data via http.get, my problem is that I cannot get a specific values of my key in typescript.
The data I am returning is in the format (json):
[
{
"id": 1,
"name": "Albany",
"manufacture": "Albany Superior Low Gi Sliced Brown Seed Bread 700g",
"price": 15.49,
"category": "Food",
"type": "Breads",
"image": "data:image/jpeg;base64,/9j/4AAQSkZJ..."
},
{
"id": 2,
"name": "Blue Ribbon",
"manufacture": "Blue Ribbon Brown Plus Low Gi Bread 700g",
"price": 13.99,
"category": "Food",
"type": "Breads",
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
}
]
In Angular, my service is as below:
export class ProductService {
prodType:ProductModel;
productList:object;
prodList: Array<ProductModel> = [];
prodMap: Map<number, ProductModel>;
constructor( private http: HttpClient ) { }
getAllProducts(): Array<ProductModel>{
this.http.get<Array<ProductModel>>('/product/service/send/all/products').subscribe(
data => {
console.log( data );
},
error => {
console.error("HTTP FAILURE ERROR!!!");
}
);
return this.prodList;
}
getProductByType( productSearch:string ){
this.productList = this.prodList.find( x=> x.getType() == productSearch);
console.log( this.productList);
}
}
The ProductModel is as follows:
export class ProductModel {
private id: number;
private name: string;
private manufacture: string;
private price: number;
private category: string;
private type: string;
private image: string;
// get and setters
The million dollar question; let's say I would to search through my data for product types and only wanted to console-log products with type milk from my json data.
How would I do that? I have searched for similar solution, but they were unhelpful.

First assign the HTTP result to your class member and then filter your datas and then console.log the filtered array items.
export class ProductService {
prodType:ProductModel;
productList:object;
prodList: Array<ProductModel> = [];
prodMap: Map<number, ProductModel>;
constructor( private http: HttpClient ) { }
getAllProducts() {
this.http.get<Array<ProductModel>>('/product/service/send/all/products').subscribe(
datas => {
this.prodList = datas;
},
error => {
console.error("HTTP FAILURE ERROR!!!");
}
);
}
getProductByType( productSearch:string ): Array<ProductModel>{
let filteredProducts:Array<ProductModel> = this.prodList.filter(product => product.type == productSearch);
filteredProducts.forEach(product=> console.log(product);
return filteredProducts;
}
}

You can add the map and modify the response coming from the http get call and filter it before assigning it to the list . of if you want to separate the same then you need split the logic into two methods one to get the vanilla list and then filter the data on top of it
getAllProducts(): Array<ProductModel>{
return this.http.get<Array<ProductModel>>('/product/service/send/all/products').map(data => data.filter(value => value.type == 'milk')).subscribe() ;
}

Related

recuperate fields of a json

I have a json like this :
[ {
"id": 1,
"libraryName": "lib1",
"bookName": "book1",
"bookPrice": 250.45,
"unitSold": 305
},
{
"id": 2,
"libraryName": "lib1",
"bookName": "book2",
"bookPrice": 450.45,
"unitSold": 150
},
{
"id": 3,
"libraryName": "lib1",
"bookName": "book3",
"bookPrice": 120.25,
"unitSold": 400
}]
I want to recuperate all the bookNames of this json in a list without creating the method getBookNames (because I want a standard way for any field of the json)
So, in the component.ts I used :
sales:any;
getSale () {
this.service.getSales().subscribe(data=> {this.sales = data,
console.log(this.sales.bookName)
})
}
It gives me undefined object in the console ! How can I solve this without creating a method getBookNames() ?
This is my class :
export interface Sale {
id: number
bookname : string
Libraryname: string
Bookprice : number
Unitsold : number
}
This is my service:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Sale } from './Sale';
#Injectable({
providedIn: 'root'
})
export class MyserviceService {
constructor(private http: HttpClient) { }
getSales () {
return this.http.get<Sale>("http://localhost:8081/sales/all")
}
}
The data obtained from the API is an array. So you could use array map() function to obtain a list of all the properties from the elements. Try the following
sales: any;
unitsSold = [];
getSale () {
this.service.getSales().subscribe(data=> {
this.sales = data,
console.log(data.map(item => item.bookName)); // <-- output: ['book1', 'book2', 'book3'];
console.log(data.map(item => item.id)); // <-- output: [1, 2, 3];
this.unitsSold = data.map(item => item.unitSold); // <-- [305, 150, 400]
});
}
I don't see anything lost here to recuperate.

best JSON Structure and getData() in Service using Interfaces & Models for Nested JSON

I have tried to find solutions that I can understand with my knowledge level. But without success. I hope that others can benefit from this question.
Currently I am trying to understand how I provide data from different nested JSON files via interfaces and models. For my example, let's say I plan to have 3 JSON files in the future. (items.json, characters.json, monsters.json)
First, I'd like to find out what a clever JSON structure looks like. (There are many example tutorials, but I did not find any for such a special case as mine)
Wich one is smarter?
First variant:
{
"wearable": {
"torso": [
{
"name": "Schlachtrobe",
"defense": 7,
"price": 22
}
],
"head": [
{
"name": "stirnband",
"defense": 2,
"price": 50
}
],
"wrist": [
// etc...
]
},
"weapons": [
// etc...
],
"consumables": [
{
"name": "Bonbon",
"effect": "Heilt um 100 TP"
},
{
"name": "Schokolade",
"effect": "Heilt um 250 TP"
}
]
}
Second variant:
[
{
"id": 1,
"category": "wearable",
"type": "torso",
"name": "Schlachtrobe",
"defense": 7,
"price": 22
},
{
"id": 2,
"category": "wearable",
"type": "head",
"name": "stirnband",
"defense": 2,
"price": 50
},
{
"id": 3,
"category": "consumables",
"name": "Bonbon",
"effect": "Heilt um 100 TP"
},
{
"id": 4,
"category": "consumables",
"name": "Schokolade",
"effect": "Heilt um 250 TP"
}
]
The second variant makes it easier to attach items (for example in the future monsters.ts) to other items. In this case, e.g. just attach the id numbers. But then each item must use the same interface structure ... Then, for example, the "Bonbon" of the category "consumable" always has an empty number field called "defense" And this is just a similiar example. There will certainly be many more empty fields.
And what is about the interfaces and the Models? I try to solve this like this:
items.interface.ts
export interface ItemsInterface {
}
export interface ArmorsInterface {
name: string;
defense: number;
price: number;
}
export interface ConsumablesInterface {
name: string;
price: number;
effect: string;
}
item.model.ts
export class ItemsModel implements ItemsInterface {
}
export class ArmorsModel implements ArmorsInterface {
name: string;
defense: number;
price: number;
constructor(obj?: any) {
this.name = (obj && obj.name) ? obj.name : '';
this.defense = (obj && obj.defense) ? obj.defense : '';
this.price = (obj && obj.price) ? obj.price : '';
}
}
export class ConsumablesModel implements ConsumablesInterface {
name: string;
price: number;
effect: string;
constructor(obj?: any) {
this.name = (obj && obj.name) ? obj.name : '';
this.price = (obj && obj.price) ? obj.price : '';
this.effect = (obj && obj.effect) ? obj.effect : '';
}
}
These could then be used in the service like this:
#Injectable()
export class ItemsService {
private items;
private _armors: BehaviorSubject<ArmorsInterface> = new BehaviorSubject(new ArmorsModel());
private _consumables: BehaviorSubject<ConsumablesInterface> = new BehaviorSubject(new ConsumablesModel());
constructor(private http: HttpClient) {
this.loadItems();
}
get getArmors() {
return this._armors.asObservable();
}
get getConsumables() {
return this._consumables.asObservable();
}
loadItems() {
this.http.get(`./assets/data/items.json`).subscribe((items: ItemsInterface) => {
this.items = items;
this._armors.next(new ArmorsModel(items));
this._consumables.next(new ConsumablesModel(items));
});
}
}
There are certainly many mistakes in the service. I am still a beginner. ;)
And in the end how you could use the service:
export class SiteHomeComponent implements OnInit {
public armors: ArmorsInterface;
constructor(private iS: ItemsService) {
}
ngOnInit() {
// Returns the Data and write it in data
this.iS.getArmors.subscribe((data) => {
this.armors = data;
});
}
}
What can be done better? Or what would you do differently? I am grateful for everything that helps me to recognize my mistakes and to learn how to do it right. Thank you for your attention. :)

Iterate through ArrayList for specific key-value in Angular 5

How do I iterate through my arrayList and return keys of of specific values? My data is in a Json format as follows:
[
{
"id": 1,
"name": "Albany",
"manufacture": "Albany Superior Low Gi Sliced Brown Seed Bread 700g",
"price": 15.49,
"category": "Food",
"type": "Breads",
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRgA..."
},
{
"id": 2,
"name": "Blue Ribbon",
"manufacture": "Blue Ribbon Brown Plus Low Gi Bread 700g",
"price": 13.99,
"category": "Food",
"type": "Breads",
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABA..."
},
{...},
{...},
...
]
I was able to return the following data:
I have written the following codes to fetch a single product for type-Milk:
#Component({
selector: 'app-milk-cream',
templateUrl: './milk-cream.component.html',
styleUrls: ['./milk-cream.component.css']
})
export class MilkCreamComponent implements OnInit {
allProducts: Array<Product> = [];
quantity: number = 1;
resultArray:any;
constructor( private prod: ProductService) { }
CallbackFunctionToFindTypeById(prod) {
return prod.type === 'Milk';
}
ngOnInit() {
this.allProducts = JSON.parse(localStorage.getItem('product-data') );
//console.log( JSON.stringify( this.allProducts ) );
var productMilk = this.allProducts.find(this.CallbackFunctionToFindTypeById);
console.log( productMilk );
}
}
interface Product {
id: number;
name: string;
manufacture: string;
price: number;
category: string;
type: string;
image: string;
}
I then edited CallbackFunctionToFindTypeById method, for it to loop and return an arrayList with products of Milk type; the problem is I could not call that method in ngOnInit (not sure that it works too):
CallbackFunctionToFindTypeById(prod) {
for (var i=0; i < this.allProducts.length; i++){
if ( prod.type === 'Milk' ){
this.allProducts[i];
}
}
return this.allProducts;
}
I am new in Angular 5 and TypeScript.
You should be using filter which returns all the items in the array that macthes the predicate
var productMilk = this.allProducts.filter(item => item.type === 'Milk');

How to map JSON response to Model in Angular 4

I have tried a lot but I am not able to get endpoint response mapped to my model. I am using HttpClient and Angular4.
I got data back from service but it is not mapped correctly to my model class.
I have following JSON which service is Returning:
{
"result": [
{
"id": "1",
"type": "User",
"contactinfo": {
"zipcode": 1111,
"name": "username"
}
}
]
}
I have created a model in typescript which I will like to map to json response:
export interface result {
zipcode: number;
name: string;
}
This is how i call JSON endpoint.
result : string[] = [];
constructor(private http: HttpClient) { }
public getList(): result[] {
this.http.get<result[]>('url...', { headers: this.headers }).subscribe(
data => {
// 1. Data is returned - Working
console.log('data: ' + data);
this.result= data;
// This is the problem. My data is not mapped to my model. If I do following a null is returned
console.log('data mapped: ' + this.result[0].name);
},
(err: HttpErrorResponse) => {
// log error
}
);
return this.result;
}
You need to import the interface in your component,
import { result } from '.result';
Your interface should look like,
interface RootObject {
result: Result[];
}
interface Result {
id: string;
type: string;
contactinfo: Contactinfo;
}
interface Contactinfo {
zipcode: number;
name: string;
}
and change the type of result as,
result : result;
and assign the result as,
this.result = data;
You can use http://www.jsontots.com/ to create the interface based on JSON
your "data" is an Object, with a property "result". result[] has a property called "contactInfo". in contactInfo you have the data you want, so
//you have no model, so NOT get<result[]>
this.http.get('url...', { headers: this.headers }).subscribe(
data => {
this.result= data.result[0].contactInfo;
}

Angular2 mapping of nested JSON arrays to model

I am trying to map the received JSON-data on my created Models. The problem is, that the JSON-data has nested arrays. So it is not possible to map my data with the way I am trying to. Is there a mistake in my way or is there a better way to map my JSON-data ?
JSON-Data
{
"data": {
"apiName": "test-application",
"stages": [
{
"stage": "prod",
"id": "xxxxxxxx",
"methods": [
{
"id": "xxxxxx",
"path": "/users/create",
"httpMethods": [
"GET"
],
"methodName": "testMethod",
"url": "https://xxxx/xxxxx/xxxxxx"
}
]
},
{
"stage": "dev",
"id": "xxxxxxx",
"methods": [
{
"id": "xxxxxxx",
"path": "/users/create",
"httpMethods": [
"GET"
],
"methodName": "testMethod",
"url": "https://xxxxx/xxxxxx/xxxx"
}
]
}
]
}
}
Models:
import {ApiStage} from "./ApiStage";
export class Api {
constructor(values: Object = {}){
Object.assign(this, values);
}
public apiName: string;
public stages: ApiStage[];
}
import {ApiMethod} from "./ApiMethod";
export class ApiStage {
constructor(values: Object = {}){
Object.assign(this, values);
}
public stage: string;
public id: string;
public methods: ApiMethod[];
}
export class ApiMethod {
constructor(values: Object = {}){
Object.assign(this, values);
}
public id: string;
public path: string;
public httpMethods: string[];
public methodName: string;
public url: string;
}
HTTP-method in service:
getApi() {
return this.http.post(this.url, this.data, {headers: this.headers})
.map(this.extractData)
.map(api => new Api(api))
.catch((error: any) => Observable.of(error.json().error || 'Server error'));
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
JSON has just a very limited set of data types - string, number, boolean, array, object. If you want to convert a JSON object tree to a tree of objects of your custom classes, it's necessary to do it recursively and with creating correct objects - not working with objects that just look like being of your classes.
This process can be tedious and error prone, so it's better to use a library such as Class transformer (https://github.com/pleerock/class-transformer) which can do it for you. You just annotate your classes with decorators (such as #Type(...)) and then you can transform plain JSON objects using plainToClass() method or serialize real objects to JSON using classToPlain().