“对象”类型上不存在属性“json”
Posted
技术标签:
【中文标题】“对象”类型上不存在属性“json”【英文标题】:Property 'json' does not exist on type 'Object' 【发布时间】:2018-02-10 19:48:21 【问题描述】:我正在尝试使用 Angular 2 HttpClient 通过 REST 获取数据。我正在关注https://angular.io/tutorial/toh-pt6 的 Angular 教程,在 Heroes 和 HTTP 部分下,您将看到这个用于通过 http 获取英雄数据的 sn-p 代码。
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);
我正在使用 InteliJ Idea,调用 response.json() 上有一条红线,即使我尝试使用 ng build 进行构建,我也会收到错误消息。
。
您可能会注意到,json().results
不是 json().data
。这是因为根据教程,服务器响应了一个具有data
字段的对象,但我自己的服务器响应了一个具有results
字段的对象。如果您将教程向下滚动一点,您就会看到这一点。
注意服务器返回的数据的形状。这个特别 内存中 Web API 示例返回具有数据属性的对象。您的 API 可能会返回其他内容。调整代码以匹配您的网络 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',但那里的答案都没有帮助我。
更新
正如 cmets 所建议的,新的 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 中的订单数组。我的组件可以像这样调用
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() 的调用是异步的,并且该方法甚至可能在获取所有数据之前返回,并且订单数组可能为空。
更新
这里要求的是handleError的代码
private handleError(error: any): Promise<any>
console.log('An error occured ', error);
return Promise.reject(error.message || error);
【问题讨论】:
HttpClient API 中没有 .json() 方法。您所遵循的教程使用旧的 Http API。请查看angular.io/guide/http 就像@Jota.Toledo 说的,有两个http 客户端——Http 和HttpClient。 HttpClient 是新的,不再使用 .json() 方法。 @matmo 感谢您的意见。我更新了我的问题。请看一看。谢谢 为什么需要返回一个promise?如果你问我,observables 会更好 你能用一个返回 observable 的解决方案来回答这个问题吗?我只需要服务返回一个订单数组,我真的不在乎它是包装在 Promise 还是 observable 中。我仍然对这些概念有所了解。还是我的问题不够清楚? 【参考方案1】:如果您来自 API 的响应是一个包含数据的对象 status: 200, data: [,,...], message: 'Data fetched successfully' 您可以按照以下方式进行操作。
首先将响应转换为字符串,然后解析响应并获取分配给对象数组的变量的数据。
this._employeeService.getEmployees()
.pipe(map(response => JSON.stringify(response)))
.subscribe(result =>
this.employeeList = JSON.parse(result).data;
// console.log(this.employeeList);
,(error)=>
console.log(error);
)
【讨论】:
绝对没有理由像那样重新序列化响应。【参考方案2】:为我修复 dotnet API 角度 MVC 应用程序
检查您的 api url,当我更新 url 时,尾随 /api/
被删除。
没有它,根 url 将返回 html,即<
【讨论】:
【参考方案3】:解决它的另一种方法是使用以下代码 sn-p:
JSON.parse(JSON.stringify(response)).data
这感觉很不对,但它有效
【讨论】:
不是一个好方法,因为从接收端它必须再次json解析才能使用它 这个方法没用。解决问题后,我使用此代码:“data as [any]”。【参考方案4】:更新:对于 rxjs > v5.5
正如一些 cmets 和其他答案中提到的,默认情况下,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))
);
请注意,您可以通过简单地调用 toPromise()
轻松地将返回的 Observable
转换为 Promise
。
原始答案:
在你的情况下,你可以
假设您的后端返回如下内容:
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[]
【讨论】:
谢谢。似乎代码假定我的服务器将返回一系列订单。我的服务器实际上返回了一个带有 .results 字段的对象,该字段是订单数组。 results: [] 之类的东西。 生病更新了,@ivange94 但我认为最好的办法是删除后端的封装级别 同样 catch 返回一个错误,即 Observable 类型上不存在属性 catch对于未来的访问者:在新的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 中包含 imports 下的模块:
...
import HttpClientModule from '@angular/common/http';
@NgModule(
imports: [
BrowserModule,
// Include it under 'imports' in your application module after BrowserModule.
HttpClientModule,
...
],
...
【讨论】:
非常简单的解释,一个简单明了的例子!如果每个人都能给出这样有用的答案,那就太好了。以上是关于“对象”类型上不存在属性“json”的主要内容,如果未能解决你的问题,请参考以下文章