Angular - HttpClient: Map Получить результат объекта метода для свойства массива
Я вызываю API, который возвращает объект JSON. Мне нужно просто значение массива для отображения в Observable. Если я вызываю api, который возвращает массив, мой сервисный вызов работает.
Ниже приведен пример кода.
// 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')
}
}
Если возвращение - объект JSON, такой как ниже, это не удается.
// 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"
}
]
}
Теперь это работает, если я просто возвращаю массив
// 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"
}
]
Как сопоставить объект JSON Observable в наблюдаемом массиве???
Ответы
Ответ 1
Вы можете просто .map()
ваш http-вызов, который является Observable
, возвратить нужный тип данных.
findAllShows(): Observable<Show[]> {
return this.http
.get('${someURL}/shows')
.map(result=>result.shows)
}
Ваш httpClient.get()
должен вернуть Observable
, о котором вы явно заявили, что он думал Observable<Show[]>
. Вы .map()
- оператор, который превращает наблюдаемое в новое.
Подробнее об операторе .map()
: http://reactivex.io/documentation/operators/map.html
Обновление:
Для RXJS версии 6 и выше просто используйте .pipe()
для передачи оператора .map()
:
findAllShows(): Observable<Show[]> {
return this.http
.get('${someURL}/shows')
.pipe(map(result=>result.shows))
}
Ответ 2
Последний HttpClient
, который следует использовать вместо http
, не имеет метода map
. Сначала вы должны импортировать его по import { map } from 'rxjs/operators';
Тогда вы должны использовать это так:
this.http.get('${someURL}/shows').pipe(
map(res => res['shows'])
)
Ответ 3
Спасибо всем, я смог найти решение, объединив ответы от @Arun Redhu, предоставив интерфейс объекта передачи, который сервер отправляет обратно. Затем решение, предоставленное @CozyAzure, с помощью.map() преобразует одно наблюдение в правильное Наблюдаемое шоу [].
Полное решение ниже для заинтересованных.
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);
}
}
Все отлично сейчас !!! Благодарю. Поэтому, в зависимости от возвращаемых данных, я могу либо использовать напрямую, либо сопоставлять их с соответствующими наблюдаемыми.
Ответ 4
.map(res=> res['shows'] )
делает трюк
Ответ 5
Есть два подхода к этому. Вы можете использовать оператор .map
из наблюдаемого для отображения одного типа наблюдаемого в другой, а второй подход - только с помощью интерфейса.
1-ый Подходы (с помощью .map
)
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
interface ItemsResponseObj {
id: string,
modified: string,
name: string
}
interface ItemsResponse {
shows: Array<ItemsResponseObj>;
}
@Injectable()
export class AppService {
constructor(private http: HttpClient) { }
getData(): Observable<ItemsResponseObj[]> {
return this.http.get<ItemsResponse>('api/api-data.json')
.map(res => res.shows);
}
}
и во втором подходе с помощью интерфейсов обертки
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
interface ItemsResponseObj {
id: string,
modified: string,
name: string
}
interface ItemsResponse {
shows: Array<ItemsResponseObj>;
}
@Injectable()
export class AppService {
constructor(private http: HttpClient) { }
getData(): Observable<ItemsResponse> {
return this.http.get<ItemsResponse>('api/api-data.json')
}
}