Angular中如何将属性不匹配的JSON响应映射到模型?
解决Angular中JSON蛇形命名到模型驼峰属性的映射问题
TypeScript接口仅作为编译时类型提示,Angular的HttpClient不会自动完成JSON字段名的转换(蛇形转驼峰)或特殊字段映射,必须手动处理数据转换。以下是三种可行方案:
方案一:在HTTP请求流中手动转换字段(最直接)
修改FlightplansService的getFlightPlans方法,利用RxJS的map操作符逐个字段映射,同时处理类型适配:
import { map } from 'rxjs/operators'; // ... 其他服务代码不变 getFlightPlans(): Observable<IFlightPlan[]> { return this.http.get<any[]>(this.apiUrl).pipe( map(rawData => rawData.map(item => ({ flightPlanId: item.flight_plan_id, aircraftIdentification: item.aircraft_identification, aircraftType: item.aircraft_type, airspeed: item.airspeed, altitude: item.altitude, flightType: item.flight_type, fuelHours: item.fuel_hours, fuelMinutes: item.fuel_minutes, departureTime: new Date(item.departure_time), arrivalTime: new Date(item.estimated_arrival_time), departureAirport: item.departing_airport, arrivalAirport: item.arrival_airport, route: item.route, remarks: item.remarks, numberOnBoard: item.number_onboard.toString() // API返回数字,接口定义为string,需转换 }))), tap(data => console.log('转换后的航班计划: ', JSON.stringify(data))), catchError(this.handleError) ); }
方案二:使用类替代接口,通过构造函数处理映射
将IFlightPlan接口改为类,在构造函数中完成JSON到类实例的转换:
export class FlightPlan { flightPlanId: string; aircraftIdentification: string; aircraftType: string; airspeed: number; altitude: number; flightType: string; fuelHours: number; fuelMinutes: number; departureTime: Date; arrivalTime: Date; departureAirport: string; arrivalAirport: string; route: string; remarks: string; numberOnBoard: string; constructor(rawData: any) { this.flightPlanId = rawData.flight_plan_id; this.aircraftIdentification = rawData.aircraft_identification; this.aircraftType = rawData.aircraft_type; this.airspeed = rawData.airspeed; this.altitude = rawData.altitude; this.flightType = rawData.flight_type; this.fuelHours = rawData.fuel_hours; this.fuelMinutes = rawData.fuel_minutes; this.departureTime = new Date(rawData.departure_time); this.arrivalTime = new Date(rawData.estimated_arrival_time); this.departureAirport = rawData.departing_airport; this.arrivalAirport = rawData.arrival_airport; this.route = rawData.route; this.remarks = rawData.remarks; this.numberOnBoard = rawData.number_onboard.toString(); } }
然后修改服务方法:
getFlightPlans(): Observable<FlightPlan[]> { return this.http.get<any[]>(this.apiUrl).pipe( map(rawData => rawData.map(item => new FlightPlan(item))), tap(data => console.log('转换后的航班计划: ', JSON.stringify(data))), catchError(this.handleError) ); }
同时将组件中flightPlans的类型改为FlightPlan[]。
方案三:通用蛇形转驼峰工具函数+特殊字段处理
若存在大量类似映射需求,可编写通用转换函数减少重复代码:
// 通用蛇形转驼峰函数 function snakeToCamel(obj: any): any { if (typeof obj !== 'object' || obj === null) return obj; if (Array.isArray(obj)) return obj.map(item => snakeToCamel(item)); return Object.keys(obj).reduce((result, key) => { const camelKey = key.replace(/_([a-z])/g, (match, char) => char.toUpperCase()); result[camelKey] = snakeToCamel(obj[key]); return result; }, {} as any); } // 服务中使用 getFlightPlans(): Observable<IFlightPlan[]> { return this.http.get<any[]>(this.apiUrl).pipe( map(rawData => rawData.map(item => { // 先批量转驼峰 const camelData = snakeToCamel(item); // 处理特殊字段映射 camelData.arrivalTime = camelData.estimatedArrivalTime; camelData.departureAirport = camelData.departingAirport; // 删除多余字段+类型转换 delete camelData.estimatedArrivalTime; delete camelData.departingAirport; camelData.departureTime = new Date(camelData.departureTime); camelData.arrivalTime = new Date(camelData.arrivalTime); camelData.numberOnBoard = camelData.numberOnboard.toString(); delete camelData.numberOnboard; return camelData as IFlightPlan; }))), tap(data => console.log('转换后的航班计划: ', JSON.stringify(data))), catchError(this.handleError) ); }
以上任意方案完成后,组件中即可正常通过flightPlan.flightPlanId、flightPlan.arrivalTime等驼峰属性访问数据。
内容的提问来源于stack exchange,提问作者Fahd
相关产品推荐
相关产品推荐

