JSONオブジェクトを返すAPIを呼び出しています。 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を配列Observableにマッピングするにはどうすればよいですか?
Http呼び出し(Observable
)を.map()
するだけで、必要なデータ型を返すことができます。
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))
}
HttpClient
の代わりに使用すべき最新のhttp
にはmap
メソッドがありません。最初にimport { map } from 'rxjs/operators';
でインポートする必要があります。次に、この方法で使用する必要があります。
this.http.get(`${someURL}/shows`).pipe(
map(res => res['shows'])
)
.map(res=> res['shows'] )
はトリックを行います
おかげで、私はサーバーが送り返す転送オブジェクトインターフェースを提供することで@ Arun Redhuからの応答を組み合わせることで解決策を見つけることができました。次に、.map()を使用して、1つのObservableを正しいObservable Show []に変換することにより、@ CozyAzureによって提供されるソリューション。
興味のある方のために以下の完全なソリューション。
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);
}
}
今はすごい!!!ありがとう。したがって、返されるデータに応じて、直接使用するか、必要な適切なObservableにマップできます。
これを行うには2つのアプローチがあります。オブザーバブルから.map
演算子を使用して、あるタイプのオブザーバブルを別のタイプにマッピングできます。2番目のアプローチには、インターフェイスの助けだけが含まれます。
最初のアプローチ(.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);
}
}
インターフェースのラッピングを使用した2番目のアプローチ
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')
}
}