如何转换Firebase snapshot.value类型适配ChatData.fromJson参数要求
Firebase Realtime Database 快照解析类型报错问题
遍历从Firebase Realtime Database获取到的数据时,需要把每条数据传入自定义的ChatData模型完成解析,但直接传入snapshot.value会触发类型报错:The argument type 'Object?' can't be assigned to the parameter type 'Map<dynamic, dynamic>?'
不清楚如何调整snapshot.value的类型才能正常完成模型转换。
直接遍历快照传值的报错代码
event.snapshot.children.forEach((snapshot) { _dataList.add(snapshot.value); msg = ChatData.fromJson(snapshot.value); });
ChatData模型的fromJson构造方法定义
ChatData.fromJson(Map<dynamic, dynamic>? json): // 将JSON转换为Message实例 uid = json?['uid'] as String, text = json?['text'] as String, timestamp = DateTime.parse(json?['timestamp'] as String), type = json?['type'] as String, filterID = json?['filterID'] as String, mumbleURL = json?['mumbleURL'] as String;
现象疑问
如果先把所有snapshot.value存入List,再遍历List逐个将元素传入ChatData.fromJson则不会触发报错,可以正常运行,相关代码如下,不清楚两种写法产生类型表现差异的原因:
event.snapshot.children.forEach((snapshot) { _dataList.add(snapshot.value); }); _dataList.forEach((element) { msg = ChatData.fromJson(element); // 此处可正常运行,原因未知 });
问题原因
- 直接遍历传值报错:Dart的静态类型检查规则中,
snapshot.value的静态声明类型为Object?,是所有类型的顶层父类,在遍历快照的上下文中,编译器无法自动推断出它的实际类型是Map<dynamic, dynamic>?,直接传入要求入参为Map类型的fromJson方法时,就会触发静态类型校验报错。 - 先存List再遍历不报错:通常是因为
_dataList没有显式声明泛型类型,属于兼容动态类型的列表,存入元素时不会做严格类型校验;后续遍历列表取出的element静态类型为dynamic,Dart对dynamic类型不会做编译期静态检查,会把类型校验推迟到运行时,只要运行时传入的数据结构和fromJson要求的Map结构匹配,就可以正常执行,不会触发编译报错。
修复方案
不要依赖dynamic类型的隐式穿透,在遍历快照时显式做类型转换即可,同时建议给列表加上明确的泛型声明,避免后续出现隐式类型问题:
// 先给_dataList加上显式泛型声明 List<Map<dynamic, dynamic>?> _dataList = []; // 遍历时显式转换类型 event.snapshot.children.forEach((snapshot) { final json = snapshot.value as Map<dynamic, dynamic>?; _dataList.add(json); msg = ChatData.fromJson(json); });
内容的提问来源于stack exchange,提问作者whatwhatwhat
相关产品推荐
相关产品推荐

