如何创建通用响应模型?解决List与Map类型转换错误
解决Flutter中API响应data字段同时兼容Map和List的问题
你的问题核心是API返回的data字段类型不固定——时而是单个Map对象,时而是List集合,但现有响应模型把data硬编码成了Map<String, dynamic>?,导致解析List时触发类型转换异常。下面给出最优雅的泛型解决方案,同时兼顾类型安全和灵活性。
通用泛型响应模型
把原来的ApiResponseModel改成泛型类,让data的类型可以动态指定,同时通过回调函数处理具体的类型解析:
class ApiResponseModel<T> { final int statusCode; final String? status; final String? message; final T? data; ApiResponseModel({ required this.statusCode, this.status, this.message, this.data, }); // 从JSON解析,传入自定义的data转换回调 factory ApiResponseModel.fromJson( Map<String, dynamic> json, T Function(dynamic data) convertData, ) { return ApiResponseModel<T>( statusCode: json['status_code'] as int, status: json['status'] as String?, message: json['message'] as String?, // 调用回调处理data的类型转换,兼容Map/List data: json['data'] != null ? convertData(json['data']) : null, ); } // 转JSON,同样传入data的序列化回调 Map<String, dynamic> toJson(Object Function(T? data) serializeData) { return { 'status_code': statusCode, 'status': status, 'message': message, 'data': data != null ? serializeData(data) : null, }; } }
实际使用示例
假设你有一个User实体类:
class User { final String userId; User({required this.userId}); factory User.fromJson(Map<String, dynamic> json) { return User(userId: json['userID'] as String); } Map<String, dynamic> toJson() { return {'userID': userId}; } }
1. 解析List类型的响应(示例1的场景)
// 假设responseJson是接口返回的JSON Map final apiResponse = ApiResponseModel<List<User>>.fromJson( responseJson, // 把List<dynamic>转成List<User> (data) => (data as List<dynamic>) .map((item) => User.fromJson(item as Map<String, dynamic>)) .toList(), ); // 之后可以安全地使用apiResponse.data(类型是List<User>?)
2. 解析Map类型的响应(示例2的场景)
final apiResponse = ApiResponseModel<User>.fromJson( responseJson, // 把Map<String, dynamic>转成User (data) => User.fromJson(data as Map<String, dynamic>), ); // 此时apiResponse.data的类型是User?
为什么这个方案更好
- 类型安全:编译时就能检查
data的类型,避免运行时类型错误 - 灵活性:不仅兼容Map和List,还能支持任意自定义类型的data
- 解耦:响应模型不用关心具体的data结构,把解析逻辑交给外部回调,符合单一职责原则
内容的提问来源于stack exchange,提问作者Augustine Onu
相关产品推荐
相关产品推荐

