当属性不匹配时,如何将JSON对象强制转换为typescript类?

时间:2017-03-02 06:09:12

标签: json angular typescript

例如,我有一个班级:

export class SomeClass {
 id: number;
 name: string;
}

我从服务器接收JSON而不是这个

[{"Id":1,"Name":"typicalname"},{"Id":2,"Name":"somename"},{"Id":3,"Name":"blablabla"},{"Id":4,"Name":"lol"},{"Id":5,"Name":"lil"},{"Id":6,"Name":"lal"}]

当属性不匹配时,如何将JSON对象强制转换为typescript类? 这就是我现在如何做到的,而且它不起作用。

getSomeClass() {
  return this.http.get(this.someClassUrl)
    .map(response => <SomeClass[]>response.json())
    .catch(this.handleError);
}

2 个答案:

答案 0 :(得分:1)

试试这个:

getSomeClass() {
  return this.http.get(this.someClassUrl)
    .map(response => {
        let json = response.json();
        return json.map(m => {
            return {
                id: json.Id,
                name: json.Name
            }
        }
    })
    .catch(this.handleError);
}

答案 1 :(得分:1)

当您有类型T和值x并且您编写<T>x时,您没有在运行时意义上执行转换。您正在执行类型断言。这意味着您告诉TypeScript x的类型是T

在这种特殊情况下,如果response.json()返回类型为any的值,这对于反序列化操作不合理,那么TypeScript编译器将为<T>response.json()接受T { {1}}。这是因为类型any与(在技术上可分配)所有内容兼容。

但是在这种情况下,您需要验证响应的形状,编译器无法为您执行此操作。您需要编写适当的验证算法。

什么是适当的将取决于您的应用程序的域,并且可能是非平凡的,但这是一个示例。不幸的是,由于您的问题意味着Angular 2和RxJS,即使是简单的适用答案也会包含相当多的偶然复杂性。

import {Http} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';

function injected(_) {} // emit decorator metadata with flag (not pertinent)

@injected export class SomeService {

  constructor(readonly http: Http) {}

  getSomeValue(): Observable<Expected> {
   return this.http.get(this.someResourceUrl)
      .catch(handleError)
      .mergeMap(response => {
        const deserialized = response.json();
        if (isExpected(deserialized)) {
          // note the type of derserialized is Expected in this block
          return Observable.of(deserialized);
        }
        return Observable.throw('response data did not have the expected shape');
      });
  }
}

export interface Expected {
  id: number;
  name: string;
}

function isExpected(deserialized : any): deserialized is Expected {
  return typeof deserialized.id === 'number' && typeof deserialized.name === 'string';
}

function handleError(error) { // this is not really necessary, but was in the question
  console.error(error); // log
  return Observable.throw(error); // rethrow.
}

这里最重要的是isExpected功能。

它采用任何类型的值,根据我们的标准验证它,并声明如果它返回true,那么给定的值确实是预期类型Expected

预期类型是什么意思?

我们的isExpected函数确定了这一点,并通过返回类型向TypeScript语言提供此信息,该类型表示如果函数返回true,则传递给它的值为{{1}类型}。

这称为用户定义类型保护功能,您可以在https://www.typescriptlang.org/docs/handbook/advanced-types.html阅读更多相关信息。