Angular2将嵌套的JSON映射到模型 - 多个请求

时间:2017-11-23 12:52:34

标签: json angular typescript mapping

我在将两个HTTP API响应映射到Angular 2中的模型时遇到问题。通过一个API调用,我得到这样的结果:

[{
    "id": 410,
    "name": "Test customdata test",
    "layer": [79,94]
}, {
    "id": 411,
    "name": "Test customdata test2",
    "layer": 79
}]

另一个请求可以给我这个

[{
    "id": 94,
    "name": "xy"
}, {
    "id": 79,
    "name": "abc"
}]

我的模型看起来像这样:

export class Dataset {
 public id: number;
 public name: string;
 public layer: Layer[];
}
export class Layer {
 public id: number;
 public name: string;
}

我怎么知道将这个JSON映射到一个模型中。我需要嵌套HTTP请求才能获取所有数据吗?如果我这样做

this.Http.get('urltogetdataset').map(response => response.json() as Dataset[] )

我得到了我的数据集对象,但当然图层参数是一个数字数组。 有没有想法的人?谢谢!

2 个答案:

答案 0 :(得分:0)

我希望你的意思是有两条独立的路线?

/api/datasets => gets you datasets
/api/layers => gets you layers

然后,您可以继续将响应映射到类:

http.get('/api/layers').map(response => {
    return response.json().map(item => new Layer().deserialize(item));
});

我建议在类中实现某种反序列化:

export class Layer {
    public id: number;
    public name: string;

    public deserialize(input){
        this.id = input.id;
        this.name = input.name;
    }
}

修改

对于数据集,请执行以下操作:

http.get('/api/datasets').map(response => {
    let dataset = response.json().map(item => {
        let dataset = new Dataset().deserialize(item)
        for(let layerId of item.layer){
            dataset.addLayer(layerService.getLayerById(layerId);
        }
        return dataset;
    });
});

这将要求数据集类具有addLayer方法。

export class Dataset {
    public id: number;
    public name: string;
    public layer: Layer[];

    public deserialize(input){
        this.id = input.id;
        this.name = input.name;
    }

    public addLayer(layer){
        this.layer.push(layer);
    }
}

此外,您需要layerService之类的内容来获取以前加载的图层ID。这是getLayerById方法的一个示例:

public getLayerById(id){
    for(let layer of this.layers){
        if(layer.id === id) return layer;
    }
}

答案 1 :(得分:0)

我认为您的API会返回每个资源的所有项目。如果不是,请告诉我。

所以,我建议你这个解决方案:

export class RESTDatasetLoader {
  ...

  retrieveDataset(): Observable<Dataset[]> {    
    return Observable.of(this.jsonDataset) //<- remplace here by the call to datasets
      .combineLatest(Observable.of(this.jsonLayer), //<- remplace here by the call to layers
          (dataset, layers) => this.mapToDataset(dataset, layers)
      )
  }

  /*
   * with your question, we have the call to dataset resource so:
   * retrieveDataset(): Observable<Dataset[]> {    
   *     return this.Http.get('urltogetdataset')
   *        .combineLatest(Observable.of(this.jsonLayer), //<- We don't have this call in your question
   *           (dataset, layers) => this.mapToDataset(dataset, layers)
   *        )
   * }
   */


  private mapToDataset(dataset: DatasetDTO[], layers: LayerDTO[]): Dataset[] {
    return dataset.map(data => {
      const mappedLayers: Layer[] = this.mapLayers(data, layers)
      return new Dataset(data.id, data.name, mappedLayers)
    })
  }

  private mapLayers(dataset: DatasetDTO, layers: LayerDTO[]): Layer[] {
    return dataset.layer
      .map(layerId => {
        const layer = layers.find(layer => layer.id === layerId)
        return new Layer(layer.id, layer.name)
      })
  }
}

在您的代码中,您必须在模块的Providers中引用RESTDatasetLoader。并且,将它注入角度分量

要获得完整代码:https://stackblitz.com/edit/angular-eoqebo?file=app%2Fapp.component.ts

同意@Aluan Haddad的回复,更喜欢界面,它是DTO(数据传输对象)。

在此之后,您将响应映射到您自己的对象,因为如果API的响应发生更改,您只需在一个位置更改,而不是在代码中的任何位置更改。

也许,如果您在Dataset响应中有一个图层,那么您的问题就会出错。它不是数组而只是数字。如果它不是错误,那么如果您可以就这一点与API团队进行交流,那么它最好总是具有相同的结构。