使用HttpClientModule在Angular 2/4中反序列化json

时间:2017-11-16 15:14:09

标签: json angular rest typescript

所以我从我的asp.net core api获得了以下JSON结构:

{
  "contentType": null,
  "serializerSettings": null,
  "statusCode": null,
  "value": {
     "productName": "Test",
     "shortDescription": "Test 123",
     "imageUri": "https://bla.com/bla",
     "productCode": null,
     "continuationToken": null
  }
}

我有以下的typescript函数调用API来获得上述响应:

public externalProduct: ProductVM;


getProductExternal(code: string): Observable<ProductVM> {
    return this.http.get("api/product?productCode=" + code)
        .map((data: ProductVM) => {
            this.externalProduct = data; //not working...
            console.log("DATA: " + data);
            console.log("DATA: " + data['value']);
            return data;
        });    
}

ProductVM:

export interface ProductVM {

    productName: string;
    shortDescription: string;
    imageUri: string;
    productCode: string;
    continuationToken: string;
}

我的问题是我无法将其反序列化为ProductVM。控制台日志只生成[object Object]

如何将json响应中value的内容实际映射到ProductVM对象?

在地图函数中说dataProductVM是不对的?我尝试了很多不同的组合,但我无法让它发挥作用!

我不确定我是否能够以某种方式自动告诉angularjson响应中的值数组映射到ProductVM对象,或者我是否应该为{{ProductVM提供构造函数1}} class(它现在是一个接口),并手动提取json中的特定值?

5 个答案:

答案 0 :(得分:4)

链接到http的map方法中的data对象被视为Object类型的对象。此类型没有您需要访问的value成员,因此类型检查器对此不满意。

键入的对象(不是any)只能分配给非类型对象或完全相同类型的对象。此处,您的数据类型为Object,无法分配给ProductVM类型的其他对象。

绕过类型检查的一种解决方案是将数据对象转换为any无类型对象。这将允许访问任何方法或成员,就像普通的旧Javascript一样。

getProductExternal(code: string): Observable<ProductVM> {
  return this.http.get("api/product?productCode=" + code)
    .map((data: any) => this.externalProduct = data.value);    
}

另一种解决方案是更改您的API,以便数据可以使用data.json()传递其内容。这样,您就不必绕过类型检查,因为json()方法返回一个无类型值。

请小心,因为如果您将来添加any对象,ProductVM对象将没有new ProductVM()的方法。您需要手动创建一个包含Object.assignvar test = $('#demo5').btnSwitch({ Theme: 'Swipe', OnText: "Active", OffText: "Inactive", ToggleState: true, OnValue: true, OffValue: false, OffCallback: function (val) { alert('you selected ' + val); }, OnCallback: function(val) { alert('you selected ' + val); } }); 的实例才能访问这些方法。

答案 1 :(得分:1)

response

因此,首先我们将响应转换为JSON。 我将它存储到value只是为了让它更清洁。然后,我们必须导航到value,因为在您的数据中ProductVM是与getProductExternal(code: string): Observable<ProductVM> { return this.http.get(`api/product?productCode=${code}`) .map(data => <ProductVM>data) .catch((error: any) => Observable.throw(error.json().error || 'Server error')); } 对应的对象。

我会这样做:

<强>服务

this.subscription = this.myService.getProductExternal(code).subscribe(
  product => this.externalProduct = product,
  error => console.warn(error)
);

<强>组件

{{1}}

答案 2 :(得分:1)

您是否尝试过更换

this.externalProduct = data;

this.externalProduct = data.json();

希望有所帮助

答案 3 :(得分:1)

From angular documentation: Typechecking http response

使用新的httpClient时必须设置返回数据的类型(因为角度为4.3)=&gt; this.http.get&LT;的 ProductVM &GT;(...

public externalProduct: ProductVM;    
getProductExternal(code: string): Observable<ProductVM> {
        return this.http.get<ProductVM>("api/product?productCode=" + code)
            .map((data: ProductVM) => {
                this.externalProduct = data; // should be allowed by typescript now
                return data;
            });    
    }
因此,打字稿应该让你安静下来

答案 4 :(得分:0)

我在使用该方法的客户端中使用了这种方法

HttpClient.get<GENERIC>(...). 

现在它正在工作。无论如何,我不明白,如果我不使用上面答案中提供的解决方案,为什么我没有收到来自HTTP客户端的T型消息。

这里是客户:

// get
get<T>(url: string, params?: [{key: string, value: string}]): Observable<T> {
var requestParams = new HttpParams()

if (params != undefined) {
  for (var kvp of params) {
    params.push(kvp);
  }
}

return this.httpClient.get<T>(url, {
  observe: 'body',
  headers: this.authHeaders,
  params: requestParams
}).pipe(
  map(
    res => <T>res
  )
);
}