Dart中如何实现动态JSON API响应的运行时模型映射
错误原因
- 你当前传入的序列化函数逻辑错误:
Team.fromJson接收的是单个Map<String,dynamic>对象,但你传入的json['data']是List<Map<String,dynamic>>类型的列表,直接传入会触发类型不匹配报错 - 泛型声明不匹配:你声明的是
ApiResponse<Team>,但实际API返回的data是List<Team>类型,泛型参数和实际返回类型不一致 - 强制类型转换错误:你写的
as List<Map<String, dynamic>>是把Team对象强转为列表,不符合逻辑,会触发运行时错误
通用动态映射解决方案
以下方案不需要单独编写多套API响应模型,同时支持单个对象、对象列表两种返回格式,可根据传入的泛型参数自动匹配返回类型:
修正后的通用响应模型代码
// 通用API响应模型,支持T为任意对象或列表类型 class ApiResponse<T> { int status; String? message; T data; ApiResponse({ required this.status, this.message, required this.data, }); // 工厂构造,接收自定义序列化函数适配不同数据类型 factory ApiResponse.fromJson(Map<String, dynamic> json, T Function(dynamic) convert) { return ApiResponse<T>( status: json['status'], message: json['message'], data: convert(json['data']), ); } }
调用示例
场景1:接口返回Team列表(当前场景)
// 转换逻辑:遍历data列表,逐个调用Team.fromJson完成序列化 return ApiResponse<List<Team>>.fromJson( json.decode(response.body), (data) => (data as List<dynamic>).map((item) => Team.fromJson(item as Map<String, dynamic>)).toList() );
场景2:接口返回单个User对象
// 假设接口返回单个User对象:"data": {"id":1, "name":"xxx", ...} return ApiResponse<User>.fromJson( json.decode(response.body), (data) => User.fromJson(data as Map<String, dynamic>) );
可选优化:运行时自动匹配目标模型
如果需要完全自动判定响应对应的模型,无需手动指定序列化逻辑,可以基于数据字段特征做自动匹配:
// 自动匹配模型的转换函数 dynamic autoConvertModel(dynamic data) { // 处理列表类型 if (data is List) { return data.map((item) => autoConvertModel(item)).toList(); } // 处理单个对象类型,根据字段特征匹配对应模型 if (data is Map<String, dynamic>) { // 存在region字段则判定为Team模型 if (data.containsKey('region')) { return Team.fromJson(data); } // 存在description字段则判定为User模型 else if (data.containsKey('description')) { return User.fromJson(data); } // 新增其他模型只需要在此处增加判断分支即可 } return data; } // 调用时直接传入自动转换函数即可,无需手动指定序列化逻辑 return ApiResponse<dynamic>.fromJson(json.decode(response.body), autoConvertModel);
内容的提问来源于stack exchange,提问作者theEUG
相关产品推荐
相关产品推荐

