打字稿,JSON:映射嵌套数组总是returns为空

Typescript, JSON: Mapping nested array always returns empty

我是 typescript 的新手,正在尝试从如下所示的 GET 请求中解析 JSON(删除了一些数据):

{  
   "currency_rate":1,
   "data":[  
     {  
        "mapIdfrom":"oslo_no",
        "refr":false,
        "duration":{  
        "total":75300,
        "return":0,
        "departure":75300
     },
     "flyTo":"STR"
    }
   ]
}

例如,我得到 "currency_rate",但是 "data" 数组是空的。

GET 请求如下所示(仅相关部分):

[...]
api_url = 'https://api.skypicker.com/flights';
[...]
let body =  {
              flyFrom: 'OSL',
              to: 'STR',
              dateFrom: '01%252F04%252F2017',
              dateTo: '20%2F04%2F2017',
              daysInDestinationFrom: 15,
              daysInDestinationTo: 20,
              returnFrom: '01%2F04%2F2017',
              returnTo: '20%2F04%2F2017',
              typeFlight: 'oneway',
              oneforcity: 0,
              one_per_date: 0,
              passengers: 1,
              adults: 1,
              children: 0,
              infants: 0,
              flyDays: '%5B0%2C1%2C2%2C3%2C4%2C5%2C6%5D',
              onlyWorkingDays: 0,
              directFlights: 0,
              partner: 'picky',
              partner_market: 'en',
              v: 2,
              xml: 0,
              curr: 'EUR',
              locale: 'en',
              price_from: 1,
              price_to: 10000,
              dtimefrom: '00%3A00',
              dtimeto: '00%3A00',
              atimefrom: '00%3A00',
              atimeto: '00%3A00',
              returndtimefrom: '00%3A00',
              returndtimeto: '00%3A00',
              returnatimefrom: '00%3A00',
              returnatimeto: '00%3A00',
              stopoverfrom: '00%3A00',
              stopoverto: '00%3A00',
              booking_token: 'hashed%20data',
              offset: 0,
              limit: 30,
              sort: 'price',
              asc: 1
            }

let bodyString = JSON.stringify(body)

return this.http.get(`${this.api_url}?${bodyString}`)
  .map(res => <SkyPickerFlight>res.json());

模型"SkyPickerFlight"定义如下:

import { SkyPickerFlightData } from '../models/skyPickerFlightData';
import { Observable } from 'rxjs/Rx';

export interface SkyPickerFlightI {
  currency: string;
  data: Observable<any[]>;
}

我也试过用 data: Observable<SkyPickerFlightData[]> 替换 data: Observable<any[]>,实际对象,但也不起作用。

在这里你可以获得完整的 GET 请求:

https://api.skypicker.com/flights?flyFrom=OSL&to=STR&dateFrom=01%2F04%2F2017&dateTo=20%2F04%2F2017&daysInDestinationFrom=15&daysInDestinationTo=20&returnFrom=01%2F04%2F2017&returnTo=20%2F04%2F2017&typeFlight=oneway&oneforcity=0&one_per_date=0&passengers=1&adults=1&children=0&infants=0&flyDays=%5B0%2C1%2C2%2C3%2C4%2C5%2C6%5D&onlyWorkingDays=0&onlyWeekends=0&directFlights=0&partner=picky&partner_market=en&v=2&xml=0&curr=EUR&locale=en&price_from=1&price_to=10000&dtimefrom=00%3A00&dtimeto=00%3A00&atimefrom=00%3A00&atimeto=00%3A00&returndtimefrom=00%3A00&returndtimeto=00%3A00&returnatimefrom=00%3A00&returnatimeto=00%3A00&stopoverfrom=00%3A00&stopoverto=00%3A00&booking_token=hashed%20data&offset=0&limit=30&sort=price&asc=1

我仍在研究它,但看起来使用 this.http.get(${this.api_url}?${bodyString}) 实际上 [=48] 的 GET 请求有点古怪=]:

{"connections":[],"currency":"EUR","del":0,"time":1,"search_params":{"to_type":"anywhere","flyFrom_type":"anywhere","seats":{"infants":0,"passengers":1,"adults":1,"children":0}},"ref_tasks":{},"currency_rate":1.0,"data":[],"refresh":[]}

与上面的 GET 请求不同的结果。不确定我是否清楚。但是像这样尝试 GET 请求(我会为您提供 URLSearchParams 的长定义)以 Bad Gateway 错误结束:

return this.http.get(this.api_url, {search: params})
  .map(res => res)

---- 编辑 ----- 在我将整个 URL 复制粘贴到:

后它起作用了
return this.http.get(<URL PASTED HERE>)
  .map(res => res)

仍然想知道如何以干净的方式传递参数,而不是将整个 URL 粘贴到那里。

您的 json 响应的一部分将不是 Observable。

尝试:

export interface SkyPickerFlightI {
  currency: string;
  data: any[];
}

您将从 http 获得一个 Observable<SkyPickerFlightI>,其中包含 currency_ratedata

我不明白你想通过 data: Observable<any[]>; 达到什么目的。正如@suraj 所说,"A section of your json response would not be an Observable".

至于答案,我认为您不需要将响应类型转换为典型的接口。一个简单的 .map(res => res.json()); 也可以。我假设你需要这样,但是,只是说让它更容易。

不确定那里是否存在问题?因此,您可以执行此操作并检查数据是否到达您的 GET:

return Observable.create(observer => {
    this.http.get(`${this.api_url}?${bodyString}`)
      .map(res => res.json())
      .subscribe((data) => {
            console.log("Data : ", data);
            observer.next(data);
      },
      (err) => {
            console.log("Error : ", err);
            observer.error(err);
      });
});

检查上面是否记录了必要的数据。如果确实如此,则像您在代码中所做的那样通过类型转换再次检查。

现在,在这里您将一个新的 Observable 返回给调用方法。因此,您也必须 subscribe() 在调用方法中。

问题出在 GET 请求上。由于某种原因,使用 URLSearchParams/RequestOptions 无效。一直收到 'BAD GATEWAY' 错误。所以我直接在 http 请求中传递了 url,如下所示:

this.http.get('https://api.skypicker.com/flights?' + bodyStringSerialized)

使用下面的序列化函数(我发现这个函数的另一个版本混淆了参数值的值,所以我删除了编码)。我用了它 'serialized(json, '')':

serialize(obj, prefix) {
var str = [], p;
for(p in obj) {
  if (obj.hasOwnProperty(p)) {
    var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
    str.push((v !== null && typeof v === "object") ?
      this.serialize(v, k) :
      k + "=" + v);
  }
}
return str.join("&");
}

感谢您的帮助!