Angular 9 中动态id键JSON API响应的模型定义与数据转换
适配Angular 9的TypeScript模型与转换实现
模型定义修正
原编写的模型代码有几处可直接调整的细节问题:
- 接口可选属性语法错误(如
text1?string缺失冒号,无法通过TS编译) - 类型不匹配:
marks在API返回中为数字格式,原代码定义为string - 动态键的
result结构未做类型适配,硬编码的类结构无法覆盖任意id的键值对场景
直接用TypeScript原生类型能力实现无冗余的模型约束:
// 单条题目详情的结构定义 export interface QuestionDetails { text1?: string; type?: string; marks?: number; choices?: string[]; answer?: string; } // 完整API响应结构,适配result下动态生成的id键 export interface ApiResponse { // Record类型自动兼容所有字符串为键、值为QuestionDetails的键值对,无需硬编码id result: Record<string, QuestionDetails>; } // 转换后输出的数组元素结构 export interface QuestionEntry { id: string; details: QuestionDetails; }
注:纯数据映射场景无需定义带构造函数的类,用interface即可完成全量类型约束,减少不必要的实例化开销。
结构转换实现
通过Object.entries遍历动态键对象,即可将嵌套结构的result转换为目标要求的对象数组:
export function transformApiResponse(rawRes: ApiResponse): QuestionEntry[] { return Object.entries(rawRes.result).map(([entryId, entryDetail]) => ({ id: entryId, details: entryDetail })); }
Angular 9 Service 接入示例
在HttpClient请求流程中通过rxjs的map操作符完成转换,组件层可直接使用处理好的结构化数组:
// question.service.ts import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { ApiResponse, QuestionEntry, transformApiResponse } from './question.models'; @Injectable({ providedIn: 'root' }) export class QuestionService { private readonly API_URL = '你的后端接口路径'; fetchQuestionList(): Observable<QuestionEntry[]> { return this.http.get<ApiResponse>(this.API_URL).pipe( map(res => transformApiResponse(res)) ); } }
常见踩坑提醒
- 原自定义类中的属性名不匹配问题:类内定义的属性为
detail(单数),构造函数赋值时写的是this.details=detail(复数),会导致赋值失败,对应属性始终为undefined - 动态键场景无需逐一声明id属性,用
Record类型即可兼顾类型安全与动态结构的兼容性
内容的提问来源于stack exchange,提问作者Hadi Mirzaei
相关产品推荐
相关产品推荐

