我正在尝试将 Django 响应转换为 Angular 的
User
数组。有几个原因,例如不同的变量名称(first_name
vs firstName
)以及 Angular User
构造函数内部有一些逻辑。
简单 Django
User
=> Angular User
服务器响应示例:
[
{"id":2,"email":"[email protected]","first_name":"Name 1","client":{"id":1}}},
{"id":3,"email":"[email protected]","first_name":"Name 2","client":{"id":2}}}
]
我想要的是转换成这种格式:
export class User {
// contructor that transforms
id: number;
email: string;
firstName: string;
isClient: boolean = false;
}
我目前已经“解决”了这个问题,但我想知道是否有更好的解决方案。
内部
something.service.ts
public getClients(): Observable<User[]> {
return this.http.get(this.getClientsUrl)
.map(r => r.json() || []).map(x => x.map(y => new User(y)));
}
当我说更好的解决方案时,虽然这有效,但它看起来不太可读。如果您执行一次,这不是问题,但是当您有很多请求时,您会开始考虑更好的解决方案(处理此问题的一种方法?)。什么是更好的方法?类似拥有的东西
return this.http.get(this.getClientsUrl)
.map(transformResponse);
应该是这样的
return this.http.get(this.getClientsUrl)
.map(r => this.transformResponse(r));
TS 界面如下所示:
interface SquareConfig {
color: string;
width?: number;
enabled: boolean;
}
您想要将给定对象转换为 TS 接口(真的)还是想让响应对象更具可读性?这完全不一样啊。
因为上面的例子“我想要的”不是TS接口。
如果您以不同的方式格式化代码并使用更明确定义的名称,那么它会更具可读性,例如
public getClients(): Observable<User[]> {
return this.http.get(this.getClientsUrl)
.map(response => response.json() || [])
.map(users => users.map(user => new User(user)));
}
我创建了一个 codepen 示例,它会注销格式正确的服务器响应。
从另一个答案中阅读您的评论:
类似这样的东西,但我希望transformResponse只实现一次,这意味着它也应该接受类作为参数。
我认为你想要TypeScript泛型,它可能看起来像这样:
public getClients<T>(type: T): Observable<T[]> {
return this.http.get(this.getClientsUrl)
.map(response => response.json() || [])
.map(clients => clients.map(client => new type(user)));
}
如果你想结合 Roman C 的方法:
public getClients(): Observable<User[]> {
return this.http.get(this.getClientsUrl)
.map(response => response.json() || [])
.map(users => users.map(user => this.mapServerResponse<User>(user, User)));
}
mapServerResponse<T>(response, type: T): T {
return new type(response);
}
我发现的一个解决方案(在 Roman C 的想法的帮助下)是扩展
Service
类。此解决方案适用于 Array
和 Object
响应。
export class ServiceUtils {
protected transformResponse(response: Response, myClass: any) {
let body = response.json();
if (body.constructor === Array) {
return body.map(element => new myClass(element)) || []
}
return new myClass(body) || new myClass();
}
}
使用方法如下:
export class SomeService extends ServiceUtils {
constructor(private http: Http) {
super(); // Unfortunate side effect
}
public getClients(): Observable<User[]> {
return this.http.get(this.getClientsUrl)
.map(response => this.transformResponse(response, User));
}
}
编辑:
更好的解决方案(无需扩展
Service
):
import { Response } from '@angular/http';
export class ServiceUtils {
public static transformResponse(response: Response, myClass: any) {
let body = response.json();
if (body.constructor === Array) {
return body.map(element => new myClass(element)) || []
}
return new myClass(body) || new myClass();
}
}
并使用它:
public getClients(): Observable<User[]> {
return this.http.get(this.getClientsUrl)
.map(r => ServiceUtils.transformResponse(r, User));
}