Flutter中API响应转List<ChildDataModel>类型转换异常排查
解决Flutter中API响应转嵌套Freezed模型的类型转换异常
核心问题分析
你遇到的List<dynamic> is not a subtype of type List<ChildDataModel>异常,本质是Dio返回的动态列表无法直接强转为强类型列表——即便用map做了转换,若没正确处理Iterable到强类型List的转换,或是Freezed模型的序列化方法调用有误,都会触发这个错误。
分步解决方案
1. 确保Freezed模型的序列化配置正确
先检查你的Freezed模型是否正确生成了fromJson方法,且配置了json_serializable依赖。
示例修正后的Freezed模型代码:
import 'package:freezed_annotation/freezed_annotation.dart'; part 'parent_data_model.freezed.dart'; part 'parent_data_model.g.dart'; @freezed class ParentDataModel with _$ParentDataModel { const factory ParentDataModel({ required List<ChildDataModel> children, // 其他业务字段... }) = _ParentDataModel; // 必须保留该方法,用于JSON反序列化 factory ParentDataModel.fromJson(Map<String, dynamic> json) => _$ParentDataModelFromJson(json); } @freezed class ChildDataModel with _$ChildDataModel { const factory ChildDataModel({ required String id, required String name, // 其他业务字段... }) = _ChildDataModel; factory ChildDataModel.fromJson(Map<String, dynamic> json) => _$ChildDataModelFromJson(json); }
注意:写完代码后必须运行
flutter pub run build_runner build,重新生成序列化相关的代码文件,确保_$XXXFromJson方法正确生成。
2. 修正Riverpod中的响应转换逻辑
不要直接对List<dynamic>强转,而是通过map逐个将JSON对象转为ChildDataModel,再调用toList()生成强类型列表。分两种场景处理:
场景1:API直接返回ChildDataModel数组
final childListProvider = FutureProvider<List<ChildDataModel>>((ref) async { final dioHelper = ref.watch(dioHelperProvider); final response = await dioHelper.get('/api/children'); // 正确转换流程:遍历动态列表→逐个转模型→生成强类型List return (response.data as List<dynamic>) .map((jsonItem) => ChildDataModel.fromJson(jsonItem as Map<String, dynamic>)) .toList(); // 关键:toList()会生成明确的List<ChildDataModel> });
场景2:API返回包含嵌套列表的ParentDataModel格式JSON
final parentDataProvider = FutureProvider<ParentDataModel>((ref) async { final dioHelper = ref.watch(dioHelperProvider); final response = await dioHelper.get('/api/parent'); // 直接用ParentDataModel的fromJson方法,Freezed会自动处理嵌套的children列表 return ParentDataModel.fromJson(response.data as Map<String, dynamic>); });
这里Freezed的序列化逻辑会自动调用
ChildDataModel.fromJson处理嵌套的子列表,无需手动遍历转换。
3. Dio请求方法的补充检查
确保你的DioHelper不要提前对响应数据做不必要的类型转换:
class DioHelper { final Dio _dio; DioHelper(this._dio); Future<Response> get(String path) async { final response = await _dio.get(path); // 直接返回原始响应,不要提前强转data的类型 return response; } }
常见错误排查点
- 忘记运行
build_runner:如果_$XXXFromJson方法不存在,会直接导致转换失败。 - map转换时未强转JSON类型:API返回的每个子项是JSON对象,必须明确强转为
Map<String, dynamic>后再调用fromJson。 - 直接强转动态列表:比如
response.data as List<ChildDataModel>,Dart不允许这种未验证元素类型的强转操作。
内容的提问来源于stack exchange,提问作者DevQt
相关产品推荐
相关产品推荐

