类型“对象"上不存在属性"json" [英] Property 'json' does not exist on type 'Object'

查看:155
本文介绍了类型“对象"上不存在属性"json"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过带角度2 HttpClient的REST来获取数据.我在这里关注角度教程 https://angular.io/tutorial/toh-pt6 英雄和HTTP 部分下,您将看到此代码段,用于通过http提取英雄数据.

I'm trying fetch data via REST with angular 2 HttpClient. I'm following the angular tutorial here https://angular.io/tutorial/toh-pt6 and under the Heroes and HTTP section you'll see this snippet of code used to fetch hero data via http.

getHeroes(): Promise<Hero[]> {
  return this.http.get(this.heroesUrl)
         .toPromise()
         .then(response => response.json().data as Hero[])
         .catch(this.handleError);
}

下面是我在应用程序中编写的类似版本

And below is a similar version I wrote in my application

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 进行构建,我也会收到错误消息.

I'm using InteliJ Idea and there's a red line on the call response.json() and even when I try to build using ng build I get the error.

类型对象"上不存在属性"json".

Property 'json' does not exist on type 'Object'.

您可能会注意到,我有json().results而不是json().data.这是因为根据本教程,服务器以具有data字段的对象作为响应,而我自己的服务器以具有results字段的对象作为响应.如果您稍微向下滚动教程,就会看到这一点.

You may notice that instead of json().data I have json().results. That's because according to the tutorial the server responded with an object that has a data field but my own server responds with an object that has a results field. If you scroll down the tutorial a bit you'll see this point.

请注意服务器返回的数据的形状.这个特别的 内存中的Web API示例返回具有数据属性的对象.你的 API可能会返回其他内容.调整代码以匹配您的网络 API.

Note the shape of the data that the server returns. This particular in-memory web API example returns an object with a data property. Your API might return something else. Adjust the code to match your web API.

为了解决这个问题,我尝试了类似的方法

In an attempt to fix this, I tried something like this

(response: Response) => response.json().results as Order[]

当我这样做时,.json()方法已解决,但是弹出了另一个错误

When I did that the .json() method was been resolved but another error popped up that

Promise类型不存在属性结果

Property results does not exist on type Promise

我尝试通过定义接口来解决此问题

I tried fixing that by defining an interface

interface OrderResponse {
    orders: Order[];
}

并修改了

 .get<OrderResponse>(url)...

但是那也不起作用.弹出另一个错误

But that also didn't work. Another error popped up

类型'OrderResponse'不能分配给类型'Response'.

Type 'OrderResponse' is not assignable to type 'Response'.

有一点要注意的是,在本教程中,他们使用了Angular HttpModule,但是在我的应用程序中,我使用的是新的Angular HttpClientModule,所以也许这就是错误的出处.

One thing note is that, in the tutorial they used the Angular HttpModule but in my application I'm using the new Angular HttpClientModule so maybe that's where the error is coming.

我是Angular 2的新手,这是我使用Angular 2构建的第一个应用程序.如果以上代码在新的HttpClientModule上不再有效,那么我将非常感谢您提供有关如何在新的HttpClientModule上实现相同功能的帮助.

I'm new to Angular 2 and this is the first app I'm building with it. If the above code is no longer valid with the new HttpClientModule I'd appreciate any help on how to achieve the same with the new HttpClientModule.

我发现了类似的问题属性"json"在类型上不存在'{}'类型"object"上不存在属性,但那里的答案都没有帮助我.

I found similar questions Property 'json' does not exist on type '{}' and Property does not exist on type 'object' but none of the answers there helped me.

更新

正如评论所建议的那样,新的HttpClientModule中没有.json()方法.对于在新模块上实现相同效果的帮助,我仍将不胜感激.在指南中,他们做了这样的事情

As the comments suggested there is no .json() method in the new HttpClientModule. I'd still appreciate help on how to achieve the same effect with the new module. From the guide they did something like this

http.get<ItemsResponse>('/api/items').subscribe(data => {
  // data is now an instance of type ItemsResponse, so you can do this:
  this.results = data.results;
});

我很理解,但是我的问题是,代码不是在组件内,而是在服务内,因此调用订阅并将结果分配给实例字段没有多大意义.

Which I understand perfectly but my problem is, that code is not within a component but a service so calling subscribe and assigning the result to a instance field won't make much sense.

我需要我的服务来返回包装在Promise中的Orders数组.我的组件可以像这样拨打电话

I need my service to return an array of Orders wrapped in a Promise. The my components can just make calls like

this.orderService.fetch(0, 10).then(orders => this.orders = orders)

我还考虑过在服务获取方法中声明一个局部变量,这样我就可以做到

I also thought of declaring a local variable in my service fetch method so that I can do

.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数组可能为空之前也可能返回.

But that doesn't make much sense to me as the call to .get() is asynchronous and the method may return even before all the data is fetch and the orders array may be empty.

更新

此处要求提供的是handleError的代码

As requested here is the code for handleError

private handleError(error: any): Promise<any> {
    console.log('An error occured ', error);
    return Promise.reject(error.message || error);
}

推荐答案

更新:适用于rxjs> v5.5

如某些评论和其他答案中所述,默认情况下, HttpClient 反序列化对对象的响应.它的某些方法允许传递通用类型参数,以便对结果进行鸭式输入.这就是为什么现在没有json()方法的原因.

As mentioned in some of the comments and other answers, by default the HttpClient deserializes the content of a response into an object. Some of its methods allow passing a generic type argument in order to duck-type the result. Thats why there is no json() method anymore.

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.

Notice that you could easily transform the returned Observable to a Promise by simply invoking toPromise().

原始答案:

就您而言,您可以

假设您的后端返回如下内容:

Assumming that your backend returns something like:

{results: [{},{}]}

JSON格式,其中每个{}是一个序列化对象,您将需要以下内容:

in JSON format, where every {} is a serialized object, you would need the following:

// 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拦截器将其归档.检查文档.例如:

I removed the catch section, as this could be archived through a HTTP interceptor. Check the docs. As example:

https://gist.github.com/jotatoledo/765c7f6d8a755613cafca97e83313b90

要消耗,只需按以下方式调用它即可:

And to consume you just need to call it like:

// In some component for example
this.fooService.fetch(...).subscribe(data => ...); // data is Order[]

这篇关于类型“对象"上不存在属性"json"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆