Dart/Flutter请求API时出现List<dynamic>非Map子类型错误
错误触发原因
_TypeError (type 'List
' is not a subtype of type 'Map<String, dynamic>')
这是Dart/Flutter进行JSON反序列化时的典型类型不匹配错误,核心触发逻辑是:代码逻辑期望接收Map<String, dynamic>类型的JSON对象作为入参,但实际传入的值是List<dynamic>类型的JSON数组,类型强转失败直接抛出异常。
本次代码的问题点
给出的代码存在以下不匹配问题:
- 接口返回的响应体经
jsonDecode处理后,顶层结构是JSON数组(格式为[{}, {}, ...]),运行时类型为List<dynamic> Areaguide.fromJson工厂方法明确要求入参为Map<String, dynamic>类型,代码直接将整个数组传入该方法,触发类型校验失败- quicktype生成的代码中已经提供了数组转对象列表的
areaguideFromJson方法,但请求逻辑中未正确使用,反而错误按单对象逻辑解析
通用排查解决方案(适用于所有同类错误)
遇到此类类型不匹配错误,按以下步骤排查解决即可:
- 第一步:确认实际数据结构
拿到原始数据源(接口响应、本地JSON文件等)后,先打印解码后数据的运行时类型:print(jsonDecode(原始字符串).runtimeType),明确顶层结构是JSON数组(List<dynamic>)还是JSON对象(Map<String, dynamic>),禁止靠主观臆断写解析逻辑。 - 第二步:匹配对应解析逻辑
如果顶层是Map<String, dynamic>(JSON对象,格式为{key: value}):直接调用单对象的fromJson方法解析即可。
如果顶层是List<dynamic>(JSON数组,格式为[item1, item2, ...]):遍历数组中的每一项,对每个属于Map<String, dynamic>的子项调用单对象fromJson方法,再组装为目标对象列表,禁止直接将整个数组传入单对象解析方法。 - 第三步:对齐类型声明
方法返回值、变量的类型声明必须和实际解析结果匹配:如果解析结果是对象列表,就不能声明为返回单个对象,避免后续调用时出现二次类型错误。 - 第四步:增加类型防御逻辑
解析前增加类型判断,兼容可能的结构变动,避免非预期结构直接导致程序崩溃,通用判断模板如下:
final decodedData = jsonDecode(rawJsonString); if (decodedData is List) { // 执行数组解析逻辑 return decodedData.map((item) => YourModel.fromJson(item as Map<String, dynamic>)).toList(); } else if (decodedData is Map<String, dynamic>) { // 执行单对象解析逻辑 return YourModel.fromJson(decodedData); } else { throw const FormatException('数据结构不符合预期'); }
本次场景修正代码
修正后的HTTP请求方法如下,直接复用quicktype生成的数组解析方法即可:
import 'dart:convert'; import 'package:arzenafees/model/areaguide.dart'; import 'package:http/http.dart' as http; // 修正返回值类型为Areaguide列表 Future<List<Areaguide>> fetcharea() async { final response = await http.get( Uri.parse('https://arz-e-nafees.nafeessolutions.com/public/api/view')); if (response.statusCode == 200) { return areaguideFromJson(response.body); } else { throw Exception('Unexpected error occured!'); } }
内容的提问来源于stack exchange,提问作者Ali Punjabi
相关产品推荐
相关产品推荐


