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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47333159/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:02:24  来源:igfitidea点击:

Deserializing json in Angular 2/4 using HttpClientModule

jsonangularresttypescript

提问by DSF

So I'm getting the following JSON structure from my asp.net coreapi:

所以我从我的asp.net coreapi得到以下 JSON 结构:

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

I have the following typescript function that invokes the API to get the above response:

我有以下打字稿函数调用 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;
}

My problem is that I can't deserialize it to ProductVM. The console logs just produce [object Object]

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

How can I actually map the contents of the valuein my json response to a ProductVMobject?

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

Is it wrong to say that datais a ProductVMin the map function? I have tried lots of different combinations but I cannot get it to work!

在 map 函数中说data是 a有错ProductVM吗?我尝试了很多不同的组合,但我无法让它工作!

I'm unsure whether I can somehow automatically tell angularto map the value array in the jsonresponse to a ProductVMobject or if I should provide a constructor to the ProductVMclass (it's an interface right now), and extract the specific values in the jsonmanually?

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

回答by Adrien Brunelat

The dataobject in the map method chained to http is considered a Objecttyped object. This type does not have the valuemember that you need to access and therefore, the type checker is not happy with it.

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

Objects that are typed (that are not any) can only be assigned to untyped objects or objects of the exact same type. Here, your data is of type Objectand cannot be assigned to another object of type ProductVM.

有类型(不是any)的对象只能分配给无类型对象或完全相同类型的对象。在这里,您的数据属于类型Object,不能分配给另一个类型为 的对象ProductVM

One solution to bypass type checking is to cast your data object to a anyuntyped object. This will allow access to any method or member just like plain old Javascript.

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

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

Another solution is to change your API so that data can deliver its content with data.json(). That way, you won't have to bypass type checking since the json() method returns an untyped value.

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

Be carefull though as your anyobject wil not have methods of the ProductVMif you ever add them in the future. You will need to manually create an instance with new ProductVM()and Object.assignon it to gain access to the methods.

但是要小心any,因为ProductVM如果您将来添加它们,您的对象将没有方法。您将需要手动创建一个带有new ProductVM()和的实例Object.assign才能访问这些方法。

回答by Pierre Mallet

From angular documentation: Typechecking http response

来自 angular 文档:Typechecking http response

You have to set the type of returned data when using new httpClient ( since angular 4.3 ) => this.http.get<ProductVM>(...

您必须在使用新的 httpClient 时设置返回数据的类型(自 angular 4.3 起)=> this.http.get< ProductVM>(...

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

thus typescript should leave you in peace

因此打字稿应该让你安心

回答by SrAxi

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

So, first we convert the response into a JSON. I store it into responsejust to make it cleaner. Then, we have to navigate to value, because in your data valueis the object that corresponds to ProductVM.

因此,首先我们将响应转换为 JSON。我response把它储存起来只是为了让它更干净。然后,我们必须导航到value,因为在您的数据中value是对应于 的对象ProductVM

I would do it like this though:

不过我会这样做:

Service

服务

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

Component

零件

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

回答by Terry Pitz

Have you tried to replace

你有没有尝试更换

this.externalProduct = data;

with

this.externalProduct = data.json();

Hope it helps

希望能帮助到你

回答by Michael Staples

I used this approach in a client which uses the method

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

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

Now it is working. Anyway, I do not understand, why I do not receive a type of T back from the http client, if I don't use the solution provided in the answer above.

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

Here is the client:

这是客户端:

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