Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - HttpClient: Map Get method object result to array property

I am calling an API that returns a JSON Object. I need just the value of the array to map to a Observable . If I call api that just returns the array my service call works.

Below is my sample code ..

// my service call ..
import { Injectable } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Show} from '../models/show';
import {HttpClient} from '@angular/common/http';

@Injectable()
export class MyService {

  constructor(private http: HttpClient ) { }


  findAllShows(): Observable<Show[]> {
    return this.http
      .get<Show[]>(`${someURL}/shows`)
  }
}

If the return is a JSON Object such as below this fails..

// Service API that FAILS ...
{
  "shows": [
    {
      "id": "123f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-13 15:54:47",
      "name": "Main Show1"
    },
    {
      "id": "456f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-14 15:54:47",
      "name": "Main Show2"
    },
    {
      "id": "789f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-17 15:54:47",
      "name": "Main Show3"
    }
  ]
}

Now this one works if I just return the Array

// Service API that Works ...
[
    {
      "id": "123f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-13 15:54:47",
      "name": "Main Show1"
    },
    {
      "id": "456f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-14 15:54:47",
      "name": "Main Show2"
    },
    {
     "id": "789f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-17 15:54:47",
      "name": "Main Show3"
    }
  ]

How do I map the JSON object Observable into an Array Observable???

like image 932
Netwobble Avatar asked Oct 12 '17 01:10

Netwobble


Video Answer


3 Answers

You can simply .map() your http call, which is an Observable, to return the data type that you want.

findAllShows(): Observable<Show[]> {
    return this.http
        .get(`${someURL}/shows`)
        .map(result=>result.shows)
}

Your httpClient.get() should return an Observable, which you have explicitly stated it thought Observable<Show[]>. You .map() is an operator that transform the observable into a new one.

More on .map() operator: http://reactivex.io/documentation/operators/map.html

Update:

For RXJS version 6 and above, simply use .pipe() to pipe the .map() operator:

findAllShows(): Observable<Show[]> {
    return this.http
        .get(`${someURL}/shows`)
        .pipe(map(result=>result.shows))
}
like image 73
CozyAzure Avatar answered Sep 17 '22 15:09

CozyAzure


Latest HttpClient which should be used instead of http has no map method. You should first import it by import { map } from 'rxjs/operators'; Then you should use it this way:

this.http.get(`${someURL}/shows`).pipe(
        map(res => res['shows'])
    )
like image 23
MajidJafari Avatar answered Sep 17 '22 15:09

MajidJafari


Thanks All, I was able to find solution by combining responses from @ Arun Redhu by providing a transfer object interface that the server sends back. Then solution provided by @CozyAzure by using the .map() to transform one Observable to the correct Observable Show[].

Full Solution below for those interested.

import {Observable} from 'rxjs/Observable';
import {Contact} from '../models/show';
import {environment} from '../../../environments/environment';
// Use the new improved HttpClient over the Http
// import {Http, Response} from '@angular/http'; 
import {HttpClient} from '@angular/common/http';

// Create a new transfer object to get data from server
interface ServerData {
  shows: Show[];
}

@Injectable()
export class ShowsService {

  constructor(private http: HttpClient ) { }

// want Observable of Show[]
  findAllShows(): Observable<Show[]> {  
    // Request as transfer object <ServerData>
    return this.http
      .get<ServerData>(`${apiURL}/shows`)
     // Map to the proper Observable I need 
      .map(res => <Show[]>res.shows); 

  }
}

All great now!!! Thanks . So depending on data returned I can either use directly or map to proper Observable I need.

like image 30
Netwobble Avatar answered Sep 17 '22 15:09

Netwobble