Dart中用Tearoff替代Lambda处理JSON转对象遇类型不匹配问题
Dart JSON解码使用方法Tearoff报错的解决
问题场景
我在Flutter/Dart开发中,用以下代码可以正常将JSON解码为User对象列表:
final jsonObject = jsonDecode(response); // ignore: unnecessary_lambdas return jsonObject.map<User>((u) => User.fromJson(u)).toList();
但代码分析器提示Closure should be a tearoff. Try using a tearoff rather than a closure,于是尝试改用方法tearoff的写法,结果均报错:
写法1:
final jsonObject = jsonDecode(response); return jsonObject.map<User>(User.fromJson).toList();
写法2:
final jsonObject = jsonDecode(response); return jsonObject.map(User.fromJson).toList();
错误信息一致:
type '(Map<String, dynamic>) => User' is not a subtype of type '(dynamic) => dynamic' of 'f'
User类的实现如下:
class User { final int id; final String name; const User({required this.id, required this.name}); factory User.fromJson(Map<String, dynamic> json) { return User( id: json['id'], name: json['name'], ); } }
问题原因
报错的核心是类型不匹配:
jsonDecode返回的是dynamic类型,jsonObject的类型也是dynamic,Dart无法自动推断出它是List<Map<String, dynamic>>。- 调用
map时,Dart默认期望入参函数的类型是(dynamic) => dynamic,但User.fromJson要求的参数类型是Map<String, dynamic>,两者无法匹配,因此抛出类型转换错误。 - 原来的闭包写法能正常运行,是因为闭包内部调用
User.fromJson(u)时,Dart会尝试对u进行隐式类型转换;而tearoff要求函数参数类型完全匹配,没有隐式转换的空间。
另外你怀疑JSON包含多余属性,这个和当前报错无关——fromJson只读取需要的字段,多余属性不会影响解码逻辑。
解决方案
要使用方法tearoff,关键是让Dart明确jsonObject的元素类型,推荐两种常用方式:
方式1:给jsonObject指定明确类型(推荐)
直接将jsonDecode的结果强转为List<Map<String, dynamic>>,让Dart知道每个元素的类型:
final List<Map<String, dynamic>> jsonObject = jsonDecode(response) as List<Map<String, dynamic>>; return jsonObject.map(User.fromJson).toList();
这样map会自动推断出需要的函数类型,User.fromJson的参数类型完全匹配,就能正常使用tearoff了。
方式2:在map时显式约束类型并转换元素
如果不想给jsonObject强转类型,也可以先将其转为明确的列表类型后再使用tearoff:
final jsonObject = jsonDecode(response); return (jsonObject as List<Map<String, dynamic>>).map(User.fromJson).toList();
内容的提问来源于stack exchange,提问作者Matthew Kooshad
相关产品推荐
相关产品推荐

