【问题标题】:Angular2 mapping nested JSON to model - multiple RequestsAngular2将嵌套的JSON映射到模型 - 多个请求
【发布时间】:2017-12-04 07:25:38
【问题描述】:

我在 Angular 2 中将两个 HTTP API 响应映射到我的模型时遇到问题。通过一个 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[] )

我得到了我的数据集对象,但当然 layer 参数是一个数字数组。 任何机构对此有想法?谢谢!

【问题讨论】:

  • 您是否已经创建了检索响应的方法?
  • 是的,我忘了将它添加到问题中。刚刚完成。
  • 您是否掌握了 API 以更改响应?
  • 改用接口
  • 好的,感谢@AluanHaddad 的输入,我以前从未使用过接口,但现在是时候改变它了 :)

标签: json angular typescript mapping


【解决方案1】:

我想您的 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 团队讨论这一点。

【讨论】:

    【解决方案2】:

    我希望你的意思是有 2 条单独的路线?

    /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;
        });
    });
    

    这将要求 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;
        }
    }
    

    【讨论】:

    • 是的 2 条单独的路线。我真的不明白这种情况下的反序列化对我有什么帮助。
    • 我更新了我的回复,向您展示如何检索各个图层并将它们添加到数据集中。反序列化可以通过@AluanHaddad 建议的接口实现。
    猜你喜欢
    • 2017-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 2020-05-14
    • 2018-01-15
    • 1970-01-01
    • 2020-03-19
    相关资源
    最近更新 更多