web-dev-qa-db-ja.com

Angular-HttpClient:Getメソッドオブジェクトの結果を配列プロパティにマップします

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にマッピングするにはどうすればよいですか?

13
Netwobble

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))
}
15
CozyAzure

HttpClientの代わりに使用すべき最新のhttpにはmapメソッドがありません。最初にimport { map } from 'rxjs/operators';でインポートする必要があります。次に、この方法で使用する必要があります。

this.http.get(`${someURL}/shows`).pipe(
        map(res => res['shows'])
    )
9
MajidJafari

.map(res=> res['shows'] )はトリックを行います

3
Sreejith sreeji

おかげで、私はサーバーが送り返す転送オブジェクトインターフェースを提供することで@ 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にマップできます。

3
Netwobble

これを行うには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')
    }

}
0
Arun Redhu