'对象'类型上不存在属性'json'
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了'对象'类型上不存在属性'json'相关的知识,希望对你有一定的参考价值。
我正在尝试使用角度为2的HttpClient通过REST获取数据。我正在遵循角度教程https://angular.io/tutorial/toh-pt6,在英雄和HTTP部分下你会看到这段代码用于通过http获取英雄数据。
getHeroes(): Promise<Hero[]> {
return this.http.get(this.heroesUrl)
.toPromise()
.then(response => response.json().data as Hero[])
.catch(this.handleError);
}
以下是我在我的应用程序中编写的类似版本
fetch(startIndex: number, limit: number): Promise<Order[]> {
let url = this.baseUrl + "&startIndex=" + startIndex + "&limit=" + limit;
return this.http.get(url)
.toPromise()
.then(response => response.json().results as Order[])
.catch(this.handleError);
}
我正在使用IntelliJ Idea,并且在调用response.json()时有一条红线,即使我尝试使用ng build构建我也会收到错误。
属性'json'在'Object'类型上不存在。
你可能会注意到,而不是json().data
我有json().results
。这是因为根据教程,服务器响应了一个具有data
字段的对象,但我自己的服务器响应了一个具有results
字段的对象。如果您向下滚动教程,您会看到这一点。
请注意服务器返回的数据的形状。此特定的内存中Web API示例返回具有data属性的对象。您的API可能会返回其他内容。调整代码以匹配您的Web API。
为了解决这个问题,我试过这样的事情
(response: Response) => response.json().results as Order[]
当我这样做时,.json()方法已被解决,但另一个错误弹出
Promise类型不存在属性结果
我尝试通过定义一个接口来修复它
interface OrderResponse {
orders: Order[];
}
并修改了get调用
.get<OrderResponse>(url)...
但那也行不通。弹出另一个错误
类型'OrderResponse'不能分配给'Response'类型。
有一点需要注意的是,在教程中他们使用了Angular HttpModule,但在我的应用程序中我使用的是新的Angular HttpClientModule,所以可能就是错误发生的地方。
我是Angular 2的新手,这是我用它构建的第一个应用程序。如果上面的代码不再对新的HttpClientModule有效,我将非常感谢有关如何使用新的HttpClientModule实现相同的帮助。
我发现了类似的问题Property 'json' does not exist on type '{}'和Property does not exist on type 'object',但没有一个答案帮助了我。
更新
正如评论所暗示的那样,新的HttpClientModule中没有.json()方法。我仍然感谢有关如何使用新模块实现相同效果的帮助。从指南他们做了这样的事情
http.get<ItemsResponse>('/api/items').subscribe(data => {
// data is now an instance of type ItemsResponse, so you can do this:
this.results = data.results;
});
我完全理解,但我的问题是,代码不在组件内,而是服务,因此调用subscribe并将结果分配给实例字段将没有多大意义。
我需要我的服务来返回一个包含在Promise中的Orders数组。我的组件只能拨打电话
this.orderService.fetch(0, 10).then(orders => this.orders = orders)
我还想过在我的服务提取方法中声明一个局部变量,这样我就能做到
.subscribe(data => {
this.orders = data.results;
}
// and out of the get call I return my local variable orders like
return Promise.resolve(orders)
但这对我来说没有多大意义,因为对.get()的调用是异步的,即使在获取所有数据并且orders数组可能为空之前,该方法也可能返回。
更新
这里要求的是handleError的代码
private handleError(error: any): Promise<any> {
console.log('An error occured ', error);
return Promise.reject(error.message || error);
}
更新:对于rxjs> v5.5
正如一些评论和其他答案中所提到的,默认情况下,HttpClient将响应的内容反序列化为对象。它的一些方法允许传递泛型类型参数以便对结果进行鸭式输入。这就是为什么没有json()
方法了。
import {throwError} from 'rxjs';
import {catchError, map} from 'rxjs/operators';
export interface Order {
// Properties
}
interface ResponseOrders {
results: Order[];
}
@Injectable()
export class FooService {
ctor(private http: HttpClient){}
fetch(startIndex: number, limit: number): Observable<Order[]> {
let params = new HttpParams();
params = params.set('startIndex',startIndex.toString()).set('limit',limit.toString());
// base URL should not have ? in it at the en
return this.http.get<ResponseOrders >(this.baseUrl,{
params
}).pipe(
map(res => res.results || []),
catchError(error => _throwError(error.message || error))
);
}
请注意,您可以通过简单地调用Observable
轻松地将返回的Promise
转换为toPromise()
。
原始答案:
在你的情况下,你可以
假设你的后端返回如下内容:
{results: [{},{}]}
在JSON格式中,每个{}都是一个序列化对象,您需要以下内容:
// Somewhere in your src folder
export interface Order {
// Properties
}
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { Order } from 'somewhere_in_src';
@Injectable()
export class FooService {
ctor(private http: HttpClient){}
fetch(startIndex: number, limit: number): Observable<Order[]> {
let params = new HttpParams();
params = params.set('startIndex',startIndex.toString()).set('limit',limit.toString());
// base URL should not have ? in it at the en
return this.http.get(this.baseUrl,{
params
})
.map(res => res.results as Order[] || []);
// in case that the property results in the res POJO doesnt exist (res.results returns null) then return empty array ([])
}
}
我删除了catch部分,因为它可以通过HTTP拦截器存档。检查the docs。例如:
https://gist.github.com/jotatoledo/765c7f6d8a755613cafca97e83313b90
而消费你只需要称之为:
// In some component for example
this.fooService.fetch(...).subscribe(data => ...); // data is Order[]
对于未来的访问者:在新的HttpClient
(Angular 4.3+)中,response
对象默认为JSON,因此您不再需要执行response.json().data
。只需直接使用response
。
示例(从官方文档修改):
import { HttpClient } from '@angular/common/http';
@Component(...)
export class YourComponent implements OnInit {
// Inject HttpClient into your component or service.
constructor(private http: HttpClient) {}
ngOnInit(): void {
this.http.get('https://api.github.com/users')
.subscribe(response => console.log(response));
}
}
不要忘记导入它并在项目的app.module.ts中包含导入模块:
...
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
BrowserModule,
// Include it under 'imports' in your application module after BrowserModule.
HttpClientModule,
...
],
...
@Voicu有正确的解决方案,谢谢你的提示。
对于未来的访问者:在新的HttpClient(Angular 4.3+)中,默认情况下响应对象是JSON,因此您不再需要执行response.json()。data。只需直接使用响应。
以上是关于'对象'类型上不存在属性'json'的主要内容,如果未能解决你的问题,请参考以下文章
vue中的Typescript - 类型'Vue |上不存在属性'validate'元素| Vue [] |元件[]'。
Vue CLI 3 typescript - 类型“Vue”上不存在属性“x”