我正在为洗车开发API服务,该服务检索大型的复杂json对象(洗车对象)。这个对象的几乎每个属性都是另一个对象,它包含简单数据类型和必须实例化的其他自定义对象 。我已经看到了很多具有1或2级属性的对象的实例,这些对象利用RxJs map函数,但是对于像这样的深层嵌套对象,这似乎并不可行。
Carwash.model.ts概述
export class Carwash {
public name: string;
public type: CARWASH_TYPE;
public rating: Rating;
public address: Address;
private _coordinates: CarwashCoordinates;
public promotions: Promotion[];
public silverPackage: Package;
public goldPackage: Package;
public platinumPackage: Package;
public exteriorPackage: Package;
public interiorPackage: Package;
public completePackage: Package;
public storeHours: StoreHours;
}
ApiService.ts
public static carwashUrl = 'http://localhost:4200/assets/data/carwash.json';
private static carwashObject: Carwash;
public name: string;
public type: CARWASH_TYPE;
public ratings: Rating[];
public address: Address;
private _coordinates: CarwashCoordinates;
public promotions: Promotion[];
public silverPackage: Package;
public goldPackage: Package;
public platinumPackage: Package;
public exteriorPackage: Package;
public interiorPackage: Package;
public completePackage: Package;
public storeHours: StoreHours;
constructor(private http: HttpClient) {
}
public getCarwash() {
console.log('getCarwash called');
if (!CarwashService.carwashObject) {
this.fetchCarwash().subscribe(
(carwash => CarwashService.carwashObject = carwash)
);
} else {
console.log('Carwash already fetched.');
}
}
private fetchCarwash(): Observable<Carwash> {
return this.http.get<any>(CarwashService.carwashUrl).pipe(
map(res => {
const carwashData = res.json();
this.name = carwashData.name; // Top level stuff is np
this.type = carwashData.type; // Top level stuff is np
for (const rating of carwashData.ratings) {
this.ratings.push(new Rating(rating.customerName,
rating.score,
rating.review,
rating.date)); // Top level stuff is np
}
this.address = // When it comes to instantiating custom objects I'm not sure how to go about it in an elegant way.
return new Carwash(this.name, this.type, etc...)
})
)
}
映射是实现此目标的唯一方法吗?我应该实现帮助函数来清理get调用吗?我不知道。
注意:不需要自定义对象结构。您需要知道的是它们由基本数据类型以及其他自定义对象组成。
答案 0 :(得分:1)
您可以执行以下操作:
http.get<CarWash>(this.carwashApiUrl).subscribe((carwash: CarWash) => console.log(carwash));
...当然,您的CarWash类需要定义所有可用的复杂属性。对于这种定义,您还可以使用Swagger编辑器之类的生成器将它们从api的类定义中删除(如果有的话)。 之后,您仍然可以将CarWashDto映射到CarWash对象,但是在UI中需要它。
答案 1 :(得分:1)
如果您需要实际的对象实例,而不仅仅是具有适当类型的形状的对象图,则可以使用如下代码:
使用Object.assign:
productsClassInstance$ = this.http.get<ProductClass>(this.productsUrl)
.pipe(
map(product => Object.assign(new ProductClass(), {
...product,
suppliers: (product.suppliers ? product.suppliers.map(supplier => Object.assign(new SupplierClass(), {
...supplier
})) : [])
}))
);
这使用map
运算符将响应映射到对象图。它利用Object.assign
创建该类的新实例,并利用散布运算符(...)将数据复制到该新实例中。
对于每个“子”对象或对象数组,您可以使用类似的代码。
[已更新为多个级别的对象]
或使用构造函数
productsClassInstanceMultipleLevels2$ = this.http.get<ProductClass[]>(this.productsUrl)
.pipe(
map(products => products.map(product =>
new ProductClass(
product.id,
product.productName,
(product.suppliers ? product.suppliers.map(supplier => new SupplierClass(
supplier.id,
supplier.name
)) : []) ))
)
);
[再次更新为使用构造函数代替Object.assign]