Dart使用GenericListResponse解析接口报List<dynamic>类型不匹配错误
错误根因
Dart 对泛型集合不存在自动递归类型转换:json.decode 反序列化接口响应时,所有 JSON 数组默认会被解析为 List<dynamic> 类型,不会自动把数组内的元素转换成你声明的 ProductReadDto 类型。你当前实现的 GenericListResponse.fromMap 直接将 json["result"] 赋值给 List<T>? 类型的 result 字段,本质是把 List<dynamic> 强转为 List<ProductReadDto> 使用,运行时就会触发类型不匹配异常。
单对象版本的 GenericResponse 也存在相同隐患,只是当前报错场景是列表返回接口,问题先暴露在列表解析逻辑上。
修复方案
给两个泛型响应类增加类型解析回调参数,在构造响应对象时手动完成 result 字段的类型转换,不需要依赖第三方库即可解决问题。
首先修改两个泛型类的实现:
import 'dart:convert'; class GenericResponse<T> { GenericResponse({ this.result, this.status = 200, this.message = "", }); factory GenericResponse.fromMap( final Map<String, dynamic> json, { required T Function(dynamic) parseResult, }) => GenericResponse( status: json["status"] ?? 200, message: json["message"] ?? "", result: json["result"] == null ? null : parseResult(json["result"]), ); factory GenericResponse.fromJson( final String str, { required T Function(dynamic) parseResult, }) => GenericResponse.fromMap(json.decode(str), parseResult: parseResult); final int status; final String message; final T? result; } class GenericListResponse<T> { GenericListResponse({ this.result, this.status = 200, this.message = "", }); factory GenericListResponse.fromMap( final dynamic json, { required T Function(dynamic) parseItem, }) => GenericListResponse( status: json["status"] ?? 200, message: json["message"] ?? "", result: json["result"] == null ? null : (json["result"] as List<dynamic>).map((item) => parseItem(item)).toList(), ); factory GenericListResponse.fromJson( final String str, { required T Function(dynamic) parseItem, }) => GenericListResponse.fromMap(json.decode(str), parseItem: parseItem); final int status; final String message; final List<T>? result; }
然后修改接口调用代码,传入对应类型的解析逻辑即可,假设ProductReadDto已经实现了fromMap命名构造函数用于反序列化:
Future<void> read({ required final Function(GenericListResponse<ProductReadDto>) onResponse, required final Function(GenericResponse response) onError, }) async => httpGet( url: "$baseUrl/Product/${type.title}", action: (Response response) => onResponse( GenericListResponse<ProductReadDto>.fromMap( response.body, // 传入列表单个元素的转换逻辑 parseItem: (itemJson) => ProductReadDto.fromMap(itemJson as Map<String, dynamic>), ) ), error: (Response response) => onError( GenericResponse.fromMap( response.body, // 错误场景可根据实际返回结构调整result解析逻辑 parseResult: (err) => err, ) ), );
如果项目中使用了json_serializable等自动序列化库,只需要把parseItem、parseResult参数里的转换逻辑替换为对应生成的反序列化方法即可,整体逻辑不需要改动。
内容的提问来源于stack exchange,提问作者SinaMN75
相关产品推荐
相关产品推荐

