Json 当属性不';不匹配?

Json 当属性不';不匹配?,json,angular,typescript,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"}] 当属性不匹配时,如

例如,我有一个类:

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);
}
getSomeClass(){
返回this.http.get(this.someClassUrl)
.map(response=>response.json())
.接住(这个.把手错误);
}
试试这个:

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

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

在这种特殊情况下,如果
response.json()
返回类型为
any
的值,这对于反序列化操作来说不是不合理的,那么对于任何
T
,TypeScript编译器将接受
response.json()
。这是因为类型
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.
}
从'@angular/Http'导入{Http};
从“rxjs/Observable”导入{Observable};
导入'rxjs/add/operator/mergeMap';
导入“rxjs/add/operator/catch”;
导入“rxjs/add/observable/of”;
函数注入({}//emit decorator元数据带有标志(不相关)
@注入导出类服务{
构造函数(只读http:http){}
getSomeValue():可观察{
返回this.http.get(this.someResourceUrl)
.catch(把手错误)
.mergeMap(响应=>{
const反序列化=response.json();
if(预期(反序列化)){
//注意,此块中需要反序列化的类型
可观察的返回(反序列化);
}
return Observable.throw('响应数据没有预期的形状');
});
}
}
需要导出接口{
id:编号;
名称:字符串;
}
函数isExpected(反序列化:any):应为反序列化{
返回typeof deserialized.id=='number'&&typeof deserialized.name=='string';
}
函数handleError(error){//这不是真正必要的,但存在问题
console.error(error);//日志
返回可观察的。抛出(错误);//重新抛出。
}
这里最重要的是
isExpected
函数

它接受任何类型的值,根据我们的标准对其进行验证,并声明如果返回true,则给定的值确实是预期的类型,
expected

属于预期类型意味着什么

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


这是一个用户定义的类型保护函数,您可以在上了解更多信息。

可能重复的@HirenParekh我看到了这个问题,但我不知道该怎么办,当属性不匹配时。在这里使用类是一种非常糟糕的做法,因为任何人尝试使用它时,
instanceof
将在运行时失败(提示使用
接口
而不是
)。您需要手动编写一个函数来验证反序列化对象的形状,以便对其进行验证?如果它是服务上使用
的方法,则如图所示传递它将失败。如果它不使用
为什么它是该类的成员?这不符合要求。它不验证反序列化对象。@AluanHaddad实际上,OP明确提到“属性不匹配”;所以问题不在于验证,这不是我对它的解释,但无论如何,函数应该通过不返回声明为类的内容来修改OP,因为考虑到实现,这是误导性的。