Angular HttpClient returns 字符串数据而不是解析的 JSON
Angular HttpClient returns string data instead of parsed JSON
我一直在将代码库从 Angular 4.x 迁移到 5.x,但我 运行 遇到了一个奇怪的问题。我有一个服务功能,旨在 return 一个对象列表到前端,然后我将其按摩成特定的数据格式。我知道我需要保留映射,但我有点生气,因为它 return 只是纯字符串数据。
原来的功能是这样的:(使用Http from @angular/http
刚重命名为HttpClient)
public GetVendors(showAll = true, screenArea: number = 0): Observable<Array<SelectModel>> {
let link = AppSettings.API_COMMON_VENDORS;
let params: URLSearchParams = new URLSearchParams();
params.set('showAll', showAll.toString());
params.set('screenArea', screenArea.toString());
let requestOptions = new RequestOptions();
requestOptions.search = params;
return this.httpClient.get(link, requestOptions).map(response => {
let result = JSON.parse(response.json());
let list = new Array<SelectModel>();
let vendors: Array<any> = result;
vendors.forEach(vendor => {
list.push(this.CreateSelectModel(vendor));
});
return list;
});
}
并且在删除所有 Http 代码之后,这里再次使用 HttpClient
来自 @angular/common/http
的函数
public GetVendors(showAll = true, screenArea: number = 0): Observable<Array<SelectModel>> {
let link = AppSettings.API_COMMON_VENDORS;
let params: HttpParams = new HttpParams()
.set('showAll', showAll.toString())
.set('screenArea', screenArea.toString());
return this.httpClient.get<Array<any>>(link, {params}).map(response => {
let list = new Array<SelectModel>();
response.forEach(vendor => {
list.push(this.CreateSelectModel(vendor));
});
return list;
});
}
这个问题有点违背了新客户端为我解析 json 的目的。 response
对象是一个字符串,表示我请求的数据的 JSON,但它仍然是字符串形式,而不是 get<>()
调用中定义的类型。
我在这里做错了什么?它不应该已经被解析了吗?
Chrome 开发工具中的响应数据示例 A'la Network Tools:
示例响应正文:
值为 response
的开发工具截图
后端 (C#) 响应如下:
[HttpGet]
public JsonResult Vendors(bool showAll = false, int screenArea = 0)
{
var vendors = _commonBL.GetVendorsSlimForUser(UserModel, UserModel.CustomerId, showAll, screenArea);
return GetJson(vendors);
}
这是在 Http => HttpClient 迁移之前它是如何工作的,并且它使用 ONE JSON.parse()
return 行中的数据只是一个标准 List<T>
我会引用 this thread 的回答。希望它能阐明事物的工作原理,彻底阅读它,它启发了我,但它并不容易找到。
TypeScript only verifies the object interface at compile time. Any object that the code fetches at runtime cannot be verified by
TypeScript.
If this is the case, then things like HttpClient.Get should not
return Observable of type T. It should return Observable of type Object because
that's what is actually returned. Trying to state that it returns T
when it returns Object is misleading.
In the documentation the client's return section says this:
@return an Observable
of the body as
type T
.
实际上,文档应该说:
@return an Observable
of the body which
might be T
. You do not get T back. If you got T back, it would
actually be T, but it's not.
这是您数据的原始响应应该的样子:
[{"Id":1234,"Name":"Chris Rutherford"}]
但这就是它实际上的样子:
"[{\"Id\":1234,\"Name\":\"Chris Rutherford\"}]"
所以在服务器代码的某处,您应用了两次 JSON 编码。一旦您更正了这一点,HttpClient
就会做正确的事情。
我一直在将代码库从 Angular 4.x 迁移到 5.x,但我 运行 遇到了一个奇怪的问题。我有一个服务功能,旨在 return 一个对象列表到前端,然后我将其按摩成特定的数据格式。我知道我需要保留映射,但我有点生气,因为它 return 只是纯字符串数据。
原来的功能是这样的:(使用Http from @angular/http
刚重命名为HttpClient)
public GetVendors(showAll = true, screenArea: number = 0): Observable<Array<SelectModel>> {
let link = AppSettings.API_COMMON_VENDORS;
let params: URLSearchParams = new URLSearchParams();
params.set('showAll', showAll.toString());
params.set('screenArea', screenArea.toString());
let requestOptions = new RequestOptions();
requestOptions.search = params;
return this.httpClient.get(link, requestOptions).map(response => {
let result = JSON.parse(response.json());
let list = new Array<SelectModel>();
let vendors: Array<any> = result;
vendors.forEach(vendor => {
list.push(this.CreateSelectModel(vendor));
});
return list;
});
}
并且在删除所有 Http 代码之后,这里再次使用 HttpClient
来自 @angular/common/http
public GetVendors(showAll = true, screenArea: number = 0): Observable<Array<SelectModel>> {
let link = AppSettings.API_COMMON_VENDORS;
let params: HttpParams = new HttpParams()
.set('showAll', showAll.toString())
.set('screenArea', screenArea.toString());
return this.httpClient.get<Array<any>>(link, {params}).map(response => {
let list = new Array<SelectModel>();
response.forEach(vendor => {
list.push(this.CreateSelectModel(vendor));
});
return list;
});
}
这个问题有点违背了新客户端为我解析 json 的目的。 response
对象是一个字符串,表示我请求的数据的 JSON,但它仍然是字符串形式,而不是 get<>()
调用中定义的类型。
我在这里做错了什么?它不应该已经被解析了吗?
Chrome 开发工具中的响应数据示例 A'la Network Tools:
示例响应正文:
值为 response
的开发工具截图
后端 (C#) 响应如下:
[HttpGet]
public JsonResult Vendors(bool showAll = false, int screenArea = 0)
{
var vendors = _commonBL.GetVendorsSlimForUser(UserModel, UserModel.CustomerId, showAll, screenArea);
return GetJson(vendors);
}
这是在 Http => HttpClient 迁移之前它是如何工作的,并且它使用 ONE JSON.parse()
return 行中的数据只是一个标准 List<T>
我会引用 this thread 的回答。希望它能阐明事物的工作原理,彻底阅读它,它启发了我,但它并不容易找到。
TypeScript only verifies the object interface at compile time. Any object that the code fetches at runtime cannot be verified by TypeScript.
If this is the case, then things like HttpClient.Get should not return Observable of type T. It should return Observable of type Object because that's what is actually returned. Trying to state that it returns T when it returns Object is misleading.
In the documentation the client's return section says this:
@return an
Observable
of the body as typeT
.实际上,文档应该说:
@return an
Observable
of the body which might beT
. You do not get T back. If you got T back, it would actually be T, but it's not.
这是您数据的原始响应应该的样子:
[{"Id":1234,"Name":"Chris Rutherford"}]
但这就是它实际上的样子:
"[{\"Id\":1234,\"Name\":\"Chris Rutherford\"}]"
所以在服务器代码的某处,您应用了两次 JSON 编码。一旦您更正了这一点,HttpClient
就会做正确的事情。