如何将 http 请求响应映射到我在 TypeScript 中定义的对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/51990839/
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
How do I map http request response to my defined object in TypeScript
提问by george007
I'm getting to know Angular, TypeScript and RxJS. I have an http request that returns a JSON. In this JSON there is data that I need to construct my defined object. Let's say, that my object is this:
我开始了解 Angular、TypeScript 和 RxJS。我有一个返回 JSON 的 http 请求。在这个 JSON 中有我需要构建我定义的对象的数据。假设我的对象是这样的:
export class RegularUser {
constructor(
public id: number,
public firstName: string,
public lastName: string,
public token: string
) {}
}
Now, I am sending a request to some API, which returns data in this format:
现在,我向某个 API 发送请求,它以这种格式返回数据:
{
success: boolean,
uid: number,
first_name: string,
last_name: string,
cid: number,
rights: number[]
token: string
}
I have the HttpClient service, so I thought I would do:
我有 HttpClient 服务,所以我想我会这样做:
this.httpClient.get(
'http://api.example.com/api/get_user'
).pipe(
tap((receivedData: Response) => console.log(receivedData)),
map((receivedData: Response) => {
return new RegularUser(
receivedData.uid,
receivedData.first_name,
receivedData.last_name,
receivedData.token);
})
);
But for TypeScript, the receivedData
object doesn't have above-listed params. Do I have to create an interface for the API response and then map it to my RegularUser
object?
但是对于 TypeScript,receivedData
对象没有上面列出的参数。我是否必须为 API 响应创建一个接口,然后将其映射到我的RegularUser
对象?
回答by Alexander Staroselsky
You can specify a typefor get()
such as an interface. Why an intermediary/additional interface may be warranted for separation of concerns in yoursitutation is that get()
with a type will notnew up an instance of class RegularUser
. An intermediary/additional interface can be created with properties you expect from the server response that will be used to create an instance of your end class:
您可以指定一个类型的get()
,如界面。为什么在您的情况下可能需要一个中间/附加接口来分离关注点,因为get()
类型不会更新 class 的实例RegularUser
。可以使用您期望从服务器响应中获得的属性创建一个中间/附加接口,这些属性将用于创建您的最终类的实例:
interface Foo {
uid: number,
first_name: string,
last_name: string,
token: string
}
this.httpClient.get<Foo>(
'http://api.example.com/api/get_user'
).pipe(
tap((receivedData: Foo) => console.log(receivedData)),
map((receivedData: Foo) => {
return new RegularUser(
receivedData.uid,
receivedData.first_name,
receivedData.last_name,
receivedData.token);
})
);
If you do not need to new up an actual instance of class RegularUser
, it may be enough it to just have it as an interface or class with properties:
如果您不需要新建 class 的实际实例RegularUser
,则将其作为具有属性的接口或类可能就足够了:
this.httpClient.get<RegularUser>(
'http://api.example.com/api/get_user'
).pipe(
tap((receivedData: RegularUser) => console.log(receivedData))
);
Hopefully that helps!
希望这有帮助!
回答by Suresh Kumar Ariya
Instead of constructor, use interface which is a better alternative. So IDE can enable code autocompletion using the Language Service and wrong naming of properties can be avoided.
使用接口代替构造函数,这是一个更好的选择。因此 IDE 可以使用语言服务启用代码自动完成,并且可以避免错误的属性命名。
export interface RegularUser {
success: boolean;
uid: number;
first_name: string;
last_name: string;
cid: number;
rights: number[];
token: string;
}
In service:
在役:
this.httpClient.get<RegularUser>(
'http://api.example.com/api/get_user'
).pipe(
tap((receivedData: RegularUser) => console.log(receivedData))
);
回答by Jeffrey Roosendaal
You can create your own Response
interface by using:
您可以Response
使用以下方法创建自己的界面:
export interface MyResponse {
success: boolean,
uid: number,
first_name: string,
last_name: string,
cid: number,
rights: number[]
token: string
}
And then import it into your service:
然后将其导入到您的服务中:
import { MyResponse } from '../some/path/filename.ts';
But you can also include it in your service itself, so you can skip 'export'
.
但是您也可以将它包含在您的服务本身中,因此您可以跳过'export'
.
You can just use it just like your current Response
interface:
您可以像当前Response
界面一样使用它:
(receivedData: MyResponse)
Note: you can give it any name you want (use TitleCase for consistency). You can also use names already used by Angular, which will then be overwritten, but that's not recommended. See comments.
注意:你可以给它任何你想要的名字(使用 TitleCase 来保持一致性)。您还可以使用 Angular 已经使用的名称,这些名称随后会被覆盖,但不建议这样做。看评论。
You may have to make some properties optional (?:
), otherwise you may get a red line indicating that 'some properties are missing' if not all are used:
您可能必须将某些属性设为可选 ( ?:
),否则您可能会看到一条红线,表明“某些属性缺失”(如果未全部使用):
...
success?: boolean,
...
Or, you can just remove the warning by making it type any
, but that's not recommended:
或者,您可以通过将其设置为 type 来删除警告any
,但不建议这样做:
(receivedData: any)
回答by Darshana
//Hey Guys I also Gained this problem then I'm trying this
import {Component, OnInit} from '@angular/core';
import {UserDetailsService} from './user-details.service';
import {ApiResponse} from '../app.component';
import {HttpClient} from '@angular/common/http';
@Component({
selector: 'app-account',
templateUrl: './account.component.html',
styleUrls: ['./account.component.css']
})
export class AccountComponent implements OnInit {
userProfile: UserProfile;
// updateSuccess: UpdateSuccess;
constructor(
private userDetailsService: UserDetailsService,
private httpClient: HttpClient
) {
}
ngOnInit() {
this.userDetailsService.getUserAccount().subscribe((response: ApiResponse<UserProfile>) => {
this.userProfile = response.payload;
});
}
}
export interface UserProfile {
firstName: string;
lastName: string;
email: string;
}