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
Deserializing json in Angular 2/4 using HttpClientModule
提问by DSF
So I'm getting the following JSON structure from my asp.net core
api:
所以我从我的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
}
}
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 value
in my json response to a ProductVM
object?
如何将value
json 响应中的内容实际映射到ProductVM
对象?
Is it wrong to say that data
is a ProductVM
in 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 angular
to map the value array in the json
response to a ProductVM
object or if I should provide a constructor to the ProductVM
class (it's an interface right now), and extract the specific values in the json
manually?
我不确定我是否可以以某种方式自动告诉angular
将json
响应中的值数组映射到ProductVM
对象,或者我是否应该为ProductVM
类提供构造函数(它现在是一个接口),并json
手动提取特定值?
回答by Adrien Brunelat
The data
object in the map method chained to http is considered a Object
typed object. This type does not have the value
member 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 Object
and 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 any
untyped 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 any
object wil not have methods of the ProductVM
if you ever add them in the future. You will need to manually create an instance with new ProductVM()
and Object.assign
on 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 response
just to make it cleaner. Then, we have to navigate to value
, because in your data value
is 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
)
);
}