【问题标题】:Deserializing json in Angular 2/4 using HttpClientModule使用 HttpClientModule 在 Angular 2/4 中反序列化 json
【发布时间】:2018-04-30 04:45:19
【问题描述】:

所以我从我的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
  }
}

我有以下 typescript 函数调用 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;
        });    
}

产品虚拟机:

export interface ProductVM {

    productName: string;
    shortDescription: string;
    imageUri: string;
    productCode: string;
    continuationToken: string;
}

我的问题是我无法将其反序列化为ProductVM。控制台日志只产生[object Object]

如何将我的 json 响应中的 value 的内容实际映射到 ProductVM 对象?

在map函数中说dataProductVM有错吗?我尝试了很多不同的组合,但我无法让它发挥作用!

我不确定我是否可以以某种方式自动告诉angularjson 响应中的值数组映射到ProductVM 对象,或者我是否应该为ProductVM 类提供构造函数(它是一个接口现在),并手动提取json中的特定值?

【问题讨论】:

  • 您的 API 返回的类型是什么?您是否还返回类似的 ProductVM?看起来您的 API 返回有某种包装器。您想要的实际数据位于 value 属性上。另外,为什么要映射结果? http get 返回一个 Observable.. 所以你可以订阅它。

标签: json angular rest typescript


【解决方案1】:

map 方法中链接到http 的data 对象被认为是Object 类型的对象。此类型没有您需要访问的 value 成员,因此类型检查器对此不满意。

类型化的对象(不是any)只能分配给无类型的对象或完全相同类型的对象。在这里,您的数据是 Object 类型的,不能分配给另一个 ProductVM 类型的对象。

绕过类型检查的一种解决方案是将数据对象转换为any 无类型对象。这将允许访问任何方法或成员,就像普通的旧 Javascript 一样。

getProductExternal(code: string): Observable<ProductVM> {
  return this.http.get("api/product?productCode=" + code)
    .map((data: any) => this.externalProduct = data.value);    
}

另一个解决方案是更改您的 API,以便数据可以使用 data.json() 传递其内容。这样,您就不必绕过类型检查,因为 json() 方法返回一个无类型的值。

要小心,因为你的 any 对象不会有 ProductVM 的方法,如果你以后添加它们的话。您将需要手动创建一个带有new ProductVM()Object.assign 的实例才能访问这些方法。

【讨论】:

  • .map(data =&gt; Object.assign(new ProductVM(), data))也应该可以工作。
  • 对嵌套对象要非常小心,因为除非手动实例化,否则它们不会被键入。
  • 嗯,就像 srAxi 的回答一样。我似乎无法在数据上调用任何东西。如果我写 data.value 我得到“属性'值'不存在于类型'对象'上。知道为什么我会收到这个编译错误吗?另外,如果我说 data.json() 它也会抱怨。悬停在数据上告诉我它是“对象”类型的。
  • 您是否尝试仅使用数据?不是 data.value
  • 那么这个衬里应该可以工作了:.map((data: any) =&gt; Object.assign(new ProductVM(), data.value)) 对吗?
【解决方案2】:

From angular documentation: Typechecking http response

在使用新的 httpClient(从 Angular 4.3 开始)时,您必须设置返回数据的类型 => this.http.getProductVM>(...

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;
            });    
    }

因此打字稿应该让你安心

【讨论】:

    【解决方案3】:

    你有没有尝试替换

    this.externalProduct = data;
    

    this.externalProduct = data.json();
    

    希望对你有帮助

    【讨论】:

      【解决方案4】:
      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;
              });    
      }
      

      所以,首先我们将响应转换为 JSON。 我将它存储到response 只是为了让它更干净。然后,我们必须导航到value,因为在您的数据中value 是对应于ProductVM 的对象。

      不过我会这样做:

      服务

      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'));    
          }
      

      组件

      this.subscription = this.myService.getProductExternal(code).subscribe(
        product => this.externalProduct = product,
        error => console.warn(error)
      );
      

      【讨论】:

      • 哦。因此,您不会将数据限制为任何类型。这完全有道理,为什么那时它会是 ProductVM。那么这一行“this.externalProduct = response.value”将对ProductVM对象进行实际的反序列化吗?我会试试这个并回复你!
      • @DSF 如果您愿意,请尝试第二种方法。我相信更干净。我希望它有所帮助。 ;)
      • 我在使用 json() 时遇到编译错误。 “对象类型上不存在属性 json”。我正在使用: import { HttpClient } from "@angular/common/http";
      • 删除 json()。我的错。 HttpClient 已经将 json() 应用于响应...
      • 然后我只是得到“'对象'类型上不存在属性'值'。将鼠标悬停在数据上告诉我它是'对象'类型,但对象上不存在值,我该如何克服这个错误?
      【解决方案5】:

      我在使用该方法的客户端中使用了这种方法

      HttpClient.get<GENERIC>(...). 
      

      现在它正在工作。无论如何,我不明白,如果我不使用上面答案中提供的解决方案,为什么我没有收到来自 http 客户端的 T 类型。

      这里是客户端:

      // 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
        )
      );
      }
      

      【讨论】:

        猜你喜欢
        • 2018-04-09
        • 1970-01-01
        • 2016-08-09
        • 2017-11-08
        • 2018-02-07
        • 1970-01-01
        • 2012-12-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多