HttpClient 如何转换嵌套 json 并映射到模型域
HttpClient how to convert nested json and map to model domain
您好,我是编程新手,几天来我一直在网上为我的问题寻找答案,但无论我做什么,都找不到适合我的答案。我收到 nest json 作为回应。 json 对象等似乎有一个动态键。我想要的是将 json 对象转换为我的模型,以便我可以轻松访问模板中的数据。感谢任何帮助
这里是 json 数据的一个例子
Amadeus API response
这是我的服务
getResults(params: any) {
this.getItiniraries(params).subscribe((res) => {
this.itinirary = res;
// console.log(res);
this.updatedResults.next(this.itinirary);
});
}
getItiniraries(params: any): Observable<Itinirary> {
return this.http.get<Itinerary>('http://localhost:4202/api/itinirary' , {params: params})
; }
模特
行程模型
import { Result } from './result.model';
import { Meta } from '@angular/platform-browser';
// Model for data from Amadeus flight affiliate search
export class Itinirary {
public meta: Meta;
public results: Result[];
constructor(res: any) {
this.meta = res.meta;
this.results = res.results;
}
}
结果模型
import { Flight } from './flight.model';
import { Fare } from './fare.model';
export class Result {
public outbound_duration: string;
public outbound_flights: Flight[];
public inbound_duration: string;
public inbound_flights: Flight[];
public fare: Fare;
public cabin_code: string;
public fare_family: string;
public travel_class: string;
public merchant: string;
public airline: string;
public deep_link: string;
constructor(result: any) {
this.outbound_duration = result.outbound.duration;
this.outbound_flights = result.outbound.flights;
this.inbound_duration = result.inbound.duration;
this.inbound_flights = result.inbound.duration;
this.fare = result.fare;
this.cabin_code = result.cabin_code;
this.fare_family = result.fare_family;
this.travel_class = result.travel_class;
this.merchant = result.merchant;
this.airline = result.airline;
this.deep_link = result.deep_link;
}
}
飞行模型
import { BookingInfo } from './bookingInfo.model';
export class Flight {
public departs_at: Date;
public arrives_at: Date;
public marketing_airline: string;
public operating_airline: string;
public flight_number: number;
public aircraft: number;
public booking_info: BookingInfo;
public origin_airport: string;
public origin_terminal: string;
public destination_airport: string;
public destination_terminal: string;
constructor(flight: any) {
this.departs_at = flight.departs_at;
this.arrives_at = flight.arrives_at;
this.marketing_airline = flight.marketing_airline;
this.operating_airline = flight.operating_airline;
this.flight_number = flight.flight_number;
this.aircraft = flight.aircraft;
this.booking_info = flight.booking_info;
this.origin_airport = flight.origin_airport;
this.origin_terminal = flight.origin_terminal;
this.destination_airport = flight.destination_airport;
this.destination_terminal = flight.destination_terminal;
}
}
元模型
import { Carrier } from './carrier.model';
export class Meta {
public carriers: {[key: string]: Carrier };
constructor(meta: any) {
this.carriers = meta.carriers;
}
}
运营商型号
export class Carrier {
public identifier: string;
public name: string;
public logoSmall: string;
public logoMedium: string;
constructor(carrier: any) {
this.identifier = carrier;
this.name = carrier.name;
this.logoSmall = carrier.logos.samll;
this.logoMedium = carrier.logos.medium;
}
}
在我的飞行模型中,我还想添加两个源自 departure_at 和 arrival_at 的属性日期和时间。
基本上我希望能够将整个 Intinirary 对象传递到我的视图,以便我可以通过字符串迭代获取值。
ex 在使用 ngFor 或 let 结果后 itinirary.results
{{ result.outbound_flights[0].departure_date }} 等
非常感谢好的指导
更新服务
getItiniraries(params: any): Observable<any> {
return this.http.get<any>('http://localhost:4202/api/itinirary' ,
{params: params})
.pipe(map((AmdResponse) => {
const parsedRes = JSON.parse(AmdResponse);
const itin = new Itinirary(parsedRes);
return itin;
} )); }
更新元模型和运营商模型
元
import { Carrier } from './carrier.model';
export class Meta {
public carriers: {[key: string]: Carrier };
constructor(meta) {
this.carriers = {};
Object.keys(meta.carriers).forEach(code => {
this.carriers[code] = new Carrier(meta.carriers[code]);
});
}
}
运营商型号
export class Carrier {
public name: string;
public logoSmall: string;
public logoMedium: string;
constructor(cObject ) {
Object.keys(cObject).forEach(code => {
this.name = cObject.name;
});
Object.keys(cObject.logo).forEach(code => {
this.logoSmall = cObject.logos.samll;
this.logoMedium = cObject.logos.medium;
});
}
}
我也像这样更新了我的结果模型。有道理吗?
import { Flight } from './flight.model';
import { Fare } from './fare.model';
export class Result {
public outbound_duration: string;
public outbound_flights: Flight[];
public inbound_duration: string;
public inbound_flights: Flight[];
public fare: Fare;
public cabin_code: string;
public fare_family: string;
public travel_class: string;
public merchant: string;
public airline: string;
public deep_link: string;
constructor(result) {
this.outbound_duration = result.outbound.duration;
// this.outbound_flights = this.loop(this.outbound_flights,
result.outbound.flights);
this.inbound_duration = result.inbound.duration;
// this.inbound_flights = this.loop(this.inbound_flights,
result.inbound.flights);
this.fare = new Fare(result.fare);
this.cabin_code = result.cabin_code;
this.fare_family = result.fare_family;
this.travel_class = result.travel_class;
this.merchant = result.merchant;
this.airline = result.airline;
this.deep_link = result.deep_link;
for (let i = 0; i < result.outbound.flights.length; i++) {
this.outbound_flights[i] = new Flight(result.outbound.flights[i]);
}
for (let i = 0; i < result.inbound.flights.length; i++) {
this.inbound_flights[i] = new Flight(result.inbound.flights[i]);
}
}
// loop(a, b) {
// for (let i = 0; i < b.length; i++) {
// a[i] = new Flight(b[i]);
// }
// return a;
// }
}
我用函数或单独的循环测试了两者。
我还在我的飞行模型中添加了一个 dateFormatterService,但是不确定将它导入到哪里,因为我无法将它导入到构造函数中。
import { BookingInfo } from './bookingInfo.model';
import { DateFormatterService } from '../../Shared/dateFormatter.service';
export class Flight {
private df: DateFormatterService; // can i have it here instead of constructor?
public departs_date: string;
public departs_time: string;
public arrives_date: string;
public arrives_time: string;
public marketing_airline: string;
public operating_airline: string;
public flight_number: number;
public aircraft: number;
public booking_info: BookingInfo;
public origin_airport: string;
public origin_terminal: string;
public destination_airport: string;
public destination_terminal: string;
constructor(flight: any ) {
const depart_at = new Date(flight.departs_at);
const arrive_at = new Date(flight.arrives_at);
this.departs_date = this.df.transformDate(depart_at);
this.departs_time = this.df.transformTime(depart_at);
this.arrives_date = this.df.transformDate(arrive_at);
this.arrives_time = this.df.transformTime(arrive_at);
this.marketing_airline = flight.marketing_airline;
this.operating_airline = flight.operating_airline;
this.flight_number = flight.flight_number;
this.aircraft = flight.aircraft;
this.booking_info = new BookingInfo(flight.booking_info);
this.origin_airport = flight.origin_airport;
this.origin_terminal = flight.origin_terminal;
this.destination_airport = flight.destination_airport;
this.destination_terminal = flight.destination_terminal;
}}
如果你想从 JSON 创建一个包含 Javascript 个模型实例的树,你可以像这样将 JSON 映射到根 class 构造函数:
getItiniraries(params: any): Observable<Itinerary> {
return this.http.get<Itinerary>('http://localhost:4202/api/itinirary', {params: params}).pipe(map(x => new Itinerary(x));
}
然后为您的所有模型定义以下构造函数 classes:
constructor(obj) {
Object.assign(this, obj);
}
然后对于模型 class 的所有子项,将这些声明 public meta: Meta;
替换为:
private _meta: Meta;
get meta() {
return this._meta;
}
set meta(value: any) {
this._meta = new Meta(value);
}
同样适用于儿童 Array
:
private _results: Result[];
get results() {
return this._results;
}
set results(value: any) {
this._results = value.map(x => new Result(x));
}
然后你的对象树将由你的模型的实例组成 classes,你将能够从你将定义的潜在功能中受益(例如数据格式化功能,或其他否则)
作为序言,请理解无法接收 JSON 字符串(来自 API 或其他地方)并使其成为特定自定义 Class 的实例。
我认为您在 Meta 构造函数中的想法是正确的....您需要将接收到的数据解析为您自己的对象。您只需要更进一步,通过将接收到的 JSON 的所有属性一次一个地显式解析为新对象(您的 classes)直到完成。可能很乏味,但如果您希望自己的 class 层次结构来表示接收到的数据(可能不需要,但这不是我可以决定的),则这是必需的。
我假设您已经从 API 响应收到的数据中获得了一个 JS 文字对象,如下所示:
const itins = JSON.parse( amadeusResponse );
然后,让您的 classes 完成工作:
const meta = new Meta( itins.meta );
//or
const alternate = new Meta();
alternate.fromJSON( itins.meta );
通过上面的内容,您可以看到您可以有一个读取 JSON 数据的方法,也可以有一个构造函数。选择将取决于您是否希望在没有先拥有 JSON 的情况下创建 Meta 对象(在这种情况下,替代方法可能更好)。
在任何一种情况下,实现都会读取您提供的 JS 对象,并将接收到的数据结构解析为您希望在本地 class 实例中拥有的结构。例如,在 Meta 构造函数中...
constructor( meta ) {
this.carriers = {};
// which carriers did we get?
Object.keys(meta.carriers).forEach( code =>
this.carriers[code] = new Carrier( code, meta.carriers[code] )
);
反过来,Carrier class 构造函数会将 "logos" 和 "name" 属性读取到其字段中,其中可能包含更多 class 实例。
继续,直到完成。
使用新的 es6 特性很容易 this._results = value.map(x => new Result(x));
可以 this._results = [...value]
这种情况下如果值是嵌套的 json 数组它会像你想要的那样平坦。
您好,我是编程新手,几天来我一直在网上为我的问题寻找答案,但无论我做什么,都找不到适合我的答案。我收到 nest json 作为回应。 json 对象等似乎有一个动态键。我想要的是将 json 对象转换为我的模型,以便我可以轻松访问模板中的数据。感谢任何帮助
这里是 json 数据的一个例子 Amadeus API response
这是我的服务
getResults(params: any) {
this.getItiniraries(params).subscribe((res) => {
this.itinirary = res;
// console.log(res);
this.updatedResults.next(this.itinirary);
});
}
getItiniraries(params: any): Observable<Itinirary> {
return this.http.get<Itinerary>('http://localhost:4202/api/itinirary' , {params: params})
; }
模特
行程模型
import { Result } from './result.model';
import { Meta } from '@angular/platform-browser';
// Model for data from Amadeus flight affiliate search
export class Itinirary {
public meta: Meta;
public results: Result[];
constructor(res: any) {
this.meta = res.meta;
this.results = res.results;
} }
结果模型
import { Flight } from './flight.model';
import { Fare } from './fare.model';
export class Result {
public outbound_duration: string;
public outbound_flights: Flight[];
public inbound_duration: string;
public inbound_flights: Flight[];
public fare: Fare;
public cabin_code: string;
public fare_family: string;
public travel_class: string;
public merchant: string;
public airline: string;
public deep_link: string;
constructor(result: any) {
this.outbound_duration = result.outbound.duration;
this.outbound_flights = result.outbound.flights;
this.inbound_duration = result.inbound.duration;
this.inbound_flights = result.inbound.duration;
this.fare = result.fare;
this.cabin_code = result.cabin_code;
this.fare_family = result.fare_family;
this.travel_class = result.travel_class;
this.merchant = result.merchant;
this.airline = result.airline;
this.deep_link = result.deep_link;
}
}
飞行模型
import { BookingInfo } from './bookingInfo.model';
export class Flight {
public departs_at: Date;
public arrives_at: Date;
public marketing_airline: string;
public operating_airline: string;
public flight_number: number;
public aircraft: number;
public booking_info: BookingInfo;
public origin_airport: string;
public origin_terminal: string;
public destination_airport: string;
public destination_terminal: string;
constructor(flight: any) {
this.departs_at = flight.departs_at;
this.arrives_at = flight.arrives_at;
this.marketing_airline = flight.marketing_airline;
this.operating_airline = flight.operating_airline;
this.flight_number = flight.flight_number;
this.aircraft = flight.aircraft;
this.booking_info = flight.booking_info;
this.origin_airport = flight.origin_airport;
this.origin_terminal = flight.origin_terminal;
this.destination_airport = flight.destination_airport;
this.destination_terminal = flight.destination_terminal;
} }
元模型
import { Carrier } from './carrier.model';
export class Meta {
public carriers: {[key: string]: Carrier };
constructor(meta: any) {
this.carriers = meta.carriers;
}
}
运营商型号
export class Carrier {
public identifier: string;
public name: string;
public logoSmall: string;
public logoMedium: string;
constructor(carrier: any) {
this.identifier = carrier;
this.name = carrier.name;
this.logoSmall = carrier.logos.samll;
this.logoMedium = carrier.logos.medium;
}
}
在我的飞行模型中,我还想添加两个源自 departure_at 和 arrival_at 的属性日期和时间。
基本上我希望能够将整个 Intinirary 对象传递到我的视图,以便我可以通过字符串迭代获取值。
ex 在使用 ngFor 或 let 结果后 itinirary.results
{{ result.outbound_flights[0].departure_date }} 等
非常感谢好的指导
更新服务
getItiniraries(params: any): Observable<any> {
return this.http.get<any>('http://localhost:4202/api/itinirary' ,
{params: params})
.pipe(map((AmdResponse) => {
const parsedRes = JSON.parse(AmdResponse);
const itin = new Itinirary(parsedRes);
return itin;
} )); }
更新元模型和运营商模型 元
import { Carrier } from './carrier.model';
export class Meta {
public carriers: {[key: string]: Carrier };
constructor(meta) {
this.carriers = {};
Object.keys(meta.carriers).forEach(code => {
this.carriers[code] = new Carrier(meta.carriers[code]);
});
}
}
运营商型号
export class Carrier {
public name: string;
public logoSmall: string;
public logoMedium: string;
constructor(cObject ) {
Object.keys(cObject).forEach(code => {
this.name = cObject.name;
});
Object.keys(cObject.logo).forEach(code => {
this.logoSmall = cObject.logos.samll;
this.logoMedium = cObject.logos.medium;
});
}
}
我也像这样更新了我的结果模型。有道理吗?
import { Flight } from './flight.model';
import { Fare } from './fare.model';
export class Result {
public outbound_duration: string;
public outbound_flights: Flight[];
public inbound_duration: string;
public inbound_flights: Flight[];
public fare: Fare;
public cabin_code: string;
public fare_family: string;
public travel_class: string;
public merchant: string;
public airline: string;
public deep_link: string;
constructor(result) {
this.outbound_duration = result.outbound.duration;
// this.outbound_flights = this.loop(this.outbound_flights,
result.outbound.flights);
this.inbound_duration = result.inbound.duration;
// this.inbound_flights = this.loop(this.inbound_flights,
result.inbound.flights);
this.fare = new Fare(result.fare);
this.cabin_code = result.cabin_code;
this.fare_family = result.fare_family;
this.travel_class = result.travel_class;
this.merchant = result.merchant;
this.airline = result.airline;
this.deep_link = result.deep_link;
for (let i = 0; i < result.outbound.flights.length; i++) {
this.outbound_flights[i] = new Flight(result.outbound.flights[i]);
}
for (let i = 0; i < result.inbound.flights.length; i++) {
this.inbound_flights[i] = new Flight(result.inbound.flights[i]);
}
}
// loop(a, b) {
// for (let i = 0; i < b.length; i++) {
// a[i] = new Flight(b[i]);
// }
// return a;
// }
}
我用函数或单独的循环测试了两者。
我还在我的飞行模型中添加了一个 dateFormatterService,但是不确定将它导入到哪里,因为我无法将它导入到构造函数中。
import { BookingInfo } from './bookingInfo.model';
import { DateFormatterService } from '../../Shared/dateFormatter.service';
export class Flight {
private df: DateFormatterService; // can i have it here instead of constructor?
public departs_date: string;
public departs_time: string;
public arrives_date: string;
public arrives_time: string;
public marketing_airline: string;
public operating_airline: string;
public flight_number: number;
public aircraft: number;
public booking_info: BookingInfo;
public origin_airport: string;
public origin_terminal: string;
public destination_airport: string;
public destination_terminal: string;
constructor(flight: any ) {
const depart_at = new Date(flight.departs_at);
const arrive_at = new Date(flight.arrives_at);
this.departs_date = this.df.transformDate(depart_at);
this.departs_time = this.df.transformTime(depart_at);
this.arrives_date = this.df.transformDate(arrive_at);
this.arrives_time = this.df.transformTime(arrive_at);
this.marketing_airline = flight.marketing_airline;
this.operating_airline = flight.operating_airline;
this.flight_number = flight.flight_number;
this.aircraft = flight.aircraft;
this.booking_info = new BookingInfo(flight.booking_info);
this.origin_airport = flight.origin_airport;
this.origin_terminal = flight.origin_terminal;
this.destination_airport = flight.destination_airport;
this.destination_terminal = flight.destination_terminal;
}}
如果你想从 JSON 创建一个包含 Javascript 个模型实例的树,你可以像这样将 JSON 映射到根 class 构造函数:
getItiniraries(params: any): Observable<Itinerary> {
return this.http.get<Itinerary>('http://localhost:4202/api/itinirary', {params: params}).pipe(map(x => new Itinerary(x));
}
然后为您的所有模型定义以下构造函数 classes:
constructor(obj) {
Object.assign(this, obj);
}
然后对于模型 class 的所有子项,将这些声明 public meta: Meta;
替换为:
private _meta: Meta;
get meta() {
return this._meta;
}
set meta(value: any) {
this._meta = new Meta(value);
}
同样适用于儿童 Array
:
private _results: Result[];
get results() {
return this._results;
}
set results(value: any) {
this._results = value.map(x => new Result(x));
}
然后你的对象树将由你的模型的实例组成 classes,你将能够从你将定义的潜在功能中受益(例如数据格式化功能,或其他否则)
作为序言,请理解无法接收 JSON 字符串(来自 API 或其他地方)并使其成为特定自定义 Class 的实例。
我认为您在 Meta 构造函数中的想法是正确的....您需要将接收到的数据解析为您自己的对象。您只需要更进一步,通过将接收到的 JSON 的所有属性一次一个地显式解析为新对象(您的 classes)直到完成。可能很乏味,但如果您希望自己的 class 层次结构来表示接收到的数据(可能不需要,但这不是我可以决定的),则这是必需的。
我假设您已经从 API 响应收到的数据中获得了一个 JS 文字对象,如下所示:
const itins = JSON.parse( amadeusResponse );
然后,让您的 classes 完成工作:
const meta = new Meta( itins.meta );
//or
const alternate = new Meta();
alternate.fromJSON( itins.meta );
通过上面的内容,您可以看到您可以有一个读取 JSON 数据的方法,也可以有一个构造函数。选择将取决于您是否希望在没有先拥有 JSON 的情况下创建 Meta 对象(在这种情况下,替代方法可能更好)。
在任何一种情况下,实现都会读取您提供的 JS 对象,并将接收到的数据结构解析为您希望在本地 class 实例中拥有的结构。例如,在 Meta 构造函数中...
constructor( meta ) {
this.carriers = {};
// which carriers did we get?
Object.keys(meta.carriers).forEach( code =>
this.carriers[code] = new Carrier( code, meta.carriers[code] )
);
反过来,Carrier class 构造函数会将 "logos" 和 "name" 属性读取到其字段中,其中可能包含更多 class 实例。
继续,直到完成。
使用新的 es6 特性很容易 this._results = value.map(x => new Result(x));
可以 this._results = [...value]
这种情况下如果值是嵌套的 json 数组它会像你想要的那样平坦。