21

我正在调用一个返回 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 映射到 Array Observable 中???

4

5 回答 5

27

您可以简单地通过.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))
}
于 2017-10-12T01:43:33.440 回答
12

最新HttpClient的应该使用而不是http没有map方法。你应该首先导入它import { map } from 'rxjs/operators'; 然后你应该这样使用它:

this.http.get(`${someURL}/shows`).pipe(
        map(res => res['shows'])
    )
于 2018-12-22T08:25:27.407 回答
6

谢谢大家,通过提供服务器发回的传输对象接口,我能够通过组合来自@Arun Redhu 的响应来找到解决方案。然后由@CozyAzure 提供的解决方案通过使用 .map() 将一个 Observable 转换为正确的 Observable Show[]。

以下为有兴趣的人提供的完整解决方案。

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。

于 2017-10-12T14:27:56.620 回答
4

.map(res=> res['shows'] ) 成功了

于 2018-03-20T15:58:30.230 回答
1

有两种方法可以做到这一点。您可以使用.map操作符形成 observable 将一种类型的 observable 映射到另一种类型,第二种方法包括仅在接口的帮助下。

第一种方法(在 的帮助下.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')
    }

}
于 2017-10-12T04:08:54.007 回答