Angular2 将 json 结果转换为接口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34516332/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular2 cast a json result to an interface
提问by Don Chambers
Using Angular2 and typescript, I have JSON returned from a webApi and I need to get it into an array of a certain type. I can't figure out how to cast the json to the interface I need.
使用 Angular2 和打字稿,我从 webApi 返回了 JSON,我需要将它放入某种类型的数组中。我不知道如何将 json 转换为我需要的接口。
My type is this interface:
我的类型是这个接口:
export interface Country {
Id: number;
Name: string;
}
My mock returns this array:
我的模拟返回这个数组:
export var COUNTRIES: Country[] = [
{ "Id": 11, "Name": "US" },
{ "Id": 12, "Name": "England" },
{ "Id": 13, "Name": "Japan" }
];
Here is my code: country.service.ts
这是我的代码:country.service.ts
@Injectable()
export class CountryService {
private _http = null;
constructor(http: Http) {
this._http = http;
}
getCountries() {
return Promise.resolve(COUNTRIES);
}
}
Then I call it with this:
然后我用这个调用它:
export class CountryPickerComponent {
public countries: Country[];
constructor(private _countryService: CountryService) { }
getCountries() {
this._countryService.getCountries().then(data => this.setData(data));
}
setData(data) {
//this.countries = data;
this.countries = JSON.parse(data);
var q = 1;
}
ngOnInit() {
this.getCountries();
}
}
As you can see, I have a class variable called countries that is an array of the Country interface. This works as expected. (I know I don't need that setData method - it's for debugging)
如您所见,我有一个名为 countries 的类变量,它是 Country 接口的数组。这按预期工作。(我知道我不需要那个 setData 方法 - 它用于调试)
Next, I changed the service to a wepApi call which returns this json.
接下来,我将服务更改为返回此 json 的 wepApi 调用。
"[{"name":"England","id":1},{"name":"France","id":2}]"
I changed the getCountries method in the service to:
我将服务中的 getCountries 方法更改为:
getCountries() {
return new Promise(resolve=>
this._http.get('http://localhost:63651/Api/membercountry')
.subscribe(data => resolve(data.json()))
);
}
Using JSON.parse, I convert this to an array which I can then use in angular2. It works. It creates the array with the data. But it's not an array implementing the Country interface.
使用 JSON.parse,我将其转换为一个数组,然后我可以在 angular2 中使用它。有用。它使用数据创建数组。但它不是实现 Country 接口的数组。
Notice that the field names from the JSON are all lower case, but the interface properties starts with an uppercase and I coded to the interface. As a result, when I got the real json it does not work. Is there a way to 'cast' this to the interface, which should throw an error and let me know something is wrong?
请注意,来自 JSON 的字段名称都是小写的,但接口属性以大写开头,并且我对接口进行了编码。结果,当我得到真正的 json 时它不起作用。有没有办法将它“投射”到界面上,它应该抛出一个错误并让我知道出了什么问题?
Many examples use map in the get as shown below:
许多示例在 get 中使用 map ,如下所示:
getCountries() {
var retVal;
return new Promise(resolve=>
this._http.get('http://localhost:63651/Api/membercountry')
.map(ref => ref.json())
.subscribe(data => resolve(data.json()))
);
}
I can't find documentation on this. When I try it I never get data but there is no error. No compile error and no runtime error.
我找不到这方面的文档。当我尝试时,我从未获得数据,但没有错误。没有编译错误,也没有运行时错误。
回答by toskv
You can do a type assertion to the interface you are expecting on the object created by JSON.parse.
您可以对 JSON.parse 创建的对象所期望的接口进行类型断言。
this.http.get('http://localhost:4200/').subscribe((value: Response) => {
let hero = <ServerInfo>value.json();
});
However this will not result in any errors if the server sends you bad objects because of 2 reasons.
但是,如果服务器由于两个原因向您发送坏对象,这不会导致任何错误。
At compile time the transpiler does not know what the server will send.
在编译时,转译器不知道服务器将发送什么。
At runtime all type information is erased since everything gets compiled to javascript.
在运行时,所有类型信息都会被删除,因为所有内容都被编译为 javascript。
回答by Matthew de Nobrega
Viktor Savkin has a library to do runtime checking of typesfor this sort of situation but it doesn't work with interfaces because Typescript doesn't export runtime information on interfaces. There is a discussion about this here.
Viktor Savkin 有一个库可以针对这种情况对类型进行运行时检查,但它不适用于接口,因为 Typescript 不会导出接口上的运行时信息。有一个关于这个的讨论在这里。
There are two possible solutions:
有两种可能的解决方案:
- If you know the data coming from the api is the correct shape, and you are just looking to give your IDE / the compiler information about this shape, you can cast as per toskv's answer.
- If you are not sure of the api and want your app to throw if the data is the wrong shape, you are going to have to implement your own check. This is a bit of overhead but it's well worth it for larger apps.
- 如果您知道来自 api 的数据是正确的形状,并且您只是想提供有关此形状的 IDE/编译器信息,则可以按照 toskv 的回答进行转换。
- 如果您不确定 api 并希望您的应用程序在数据形状错误时抛出,您将不得不实施自己的检查。这有点开销,但对于较大的应用程序来说非常值得。
In general I see Typescript's types as compiler hints more than a rigorous type system - it has to compile down to an untyped language after all.
一般来说,我将 Typescript 的类型视为编译器提示,而不是严格的类型系统 - 毕竟它必须编译为无类型语言。

