Flutter Dart JSON转模型时指定Map<String,dynamic>参数触发类型不匹配报错
报错底层原因
1. JSON解析后的默认泛型规则
通过json.decode反序列化得到的所有集合类型,静态类型默认都携带dynamic泛型:
- 外层JSON对象静态类型为
Map<String, dynamic>,所有value的静态类型都是dynamic - 你代码中
json["data"]虽然运行时是数组,但静态类型是dynamic,Dart会将其当做List<dynamic>处理,数组中每个元素的静态类型都是dynamic,而非你预期的Map<String, dynamic>。
2. List.map方法的类型约束
List<T>的map方法要求传入的转换函数类型为R Function(T),即参数类型必须和列表的泛型完全匹配。
你当前场景下列表泛型是dynamic,所以map要求传入的函数类型为(dynamic) => dynamic。
3. Dart函数参数的逆变特性
Dart的函数参数类型遵循逆变规则:如果要求传入一个接受T类型参数的函数,只能传入参数类型为T或T父类型的函数,不能传入参数类型为T子类型的函数。
你写的(Map<String, dynamic> x) => University.fromJson(x)是参数类型为Map<String, dynamic>的函数,而Map<String, dynamic>是dynamic的子类型,不符合map要求的参数类型,因此触发类型不匹配报错。
为什么修改参数类型为dynamic就正常
当你把回调的参数x设为dynamic或者不写类型(Dart自动推断为dynamic),转换函数的类型就变成了(dynamic) => University,符合map要求的(dynamic) => dynamic的类型约束。且运行时x实际就是Map<String, dynamic>类型,传给University.fromJson不会出现运行时错误。
更规范的写法
如果你希望明确指定x的类型为Map<String, dynamic>,可以先将数组做泛型强转:
data: json["data"] == null ? null : List<University>.from( (json["data"] as List).cast<Map<String, dynamic>>().map((Map<String, dynamic> x) => University.fromJson(x)), ),
内容的提问来源于stack exchange,提问作者Hazar Belge
相关产品推荐
相关产品推荐

