将可观察到的嵌套对象映射到另一个对象

时间:2018-10-02 09:50:50

标签: angular typescript mapping observable rxjs6

我正在尝试将API调用的响应映射到一个Product对象。我似乎找不到适当的方法。

响应采用以下结构:

{
  "data": [
    {
      "id": 1,
      "name": "keyboard",
      "details": {
        "parent": 1,
        "price": 50,
        "other": "info"
      }
    },
    {
      "id": 2,
      "name": "mouse",
      "details": {
        "parent": 2,
        "other": "info",
        "price": 20
      }
    }
  ],
  "total-records": 2,
  "more": "something"
}

不能保证响应详细信息的顺序。 (请注意价格)。我正在尝试将上面的对象映射到一个仅包含以下属性的新对象:

{
    "id": 1,
    "name": "keyboard",
    "price": 50
},
{
    "id": 2,
    "name": "mouse",
    "price": 20
}

我正在使用angular和Observables来获取数据。现在,我获取了值并将其映射,并且可以只获取详细信息或第一级对象属性,例如data.iddata.name。但是,获取价格之类的细节会让我感到困惑。

我已经研究了很多关于mergemap,flatmap,甚至lodash和无数小时的尝试,但是我似乎找不到正确的方法。

我可以在地图的组合中使用过滤器来实现此目的吗? 任何信息都将受到高度赞赏。

到目前为止,这是我的代码:

ngOnInit() {
    //Get by criteria
    this.productService
      .get(url, httpOptions)
      .pipe(
        map((items: Response<Product>) => {
          this.details = items["details"].filter(
            // Filter possible null values
            details=> details!==null;
          );
          this.header = items
        }),
        tap(() => console.log(this.header))
      )
      .subscribe();
  }
  
  // Header is level 1 info like name and id
  // Detail is level 2 info like price.
  // I have to have a filter on the details because sometimes 

2 个答案:

答案 0 :(得分:0)

它在那里不依赖RxJS,而是依赖简单的旧Javascript。

要将对象映射到期望的对象,请尝试以下操作:

this.productService
  .get(url, httpOptions)
  .pipe(
    map((items: Response<Product>) => items
      .map(item => ({ id: item.id, name: item.name, price: item.details && item.details.price || '?' }))),
    tap(mappedItems => console.log(mappedItems))
  )
  .subscribe(mappedItems => this.header = mappedItems);

我还可以随意移动代码以使其更清晰(例如,在订阅中而不是直接在地图中进行操作)。

此代码的作用是映射Observable,使其返回一组新数据。

返回的新数据集也是一个映射,但是是实际数据的映射,而不是Observable的映射。

有了映射的数据,您现在可以将其应用到您的标头中,该标头是在订阅中创建的。

答案 1 :(得分:0)

从RxJS运算符内部分配“全局”是一种奇怪的工作方式。这些var应该从订阅中添加。而且捕获数据的方式也很奇怪。

您永远不会从响应中捕获“数据”属性,而将“细节”视为数组,但在响应中它是简单的对象。

继您的API重新使用之后,具有至少3个属性的1个对象 数据产品列表, 总记录更多 ...,

您可以做什么:

this.productService
  .get(url, httpOptions).pipe(
      map((res) => res.data), // extract data attribut
      map((data) => {
        return data.map((aProd) => {   //map the product and take only id, name, price
          return {
            id: aProd.id,
            name: aProd.name,
            price: aProd.details && aProd.details.price
          };
        });
      })).subscribe((productList) => {
        console.log(productList);
      });