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???
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
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))
}
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'])
)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With