Flutter中如何将Hive Box返回的Map<dynamic,dynamic>转为Map<String,dynamic>
Hive存储Map<String, dynamic>取出变为Map<dynamic, dynamic>的解决方法
问题详情
通过toJson()方法将Map<String, dynamic>存入Hive Box,但取出时得到的是Map<dynamic, dynamic>。尝试直接用jsonDecode()转换报错(提示'_Map<dynamic, dynamic>' is not a subtype of type 'String'),先转String再经jsonEncode()和jsonDecode()处理也失败,报错"Converting object to an encodable object failed: Instance of 'DateTime'"。非Map类型数据存取正常。
相关代码:
final HiveHelper hh = HiveHelper(); final box = Hive.openBox('boxip'); ... ... Future<void> saveDataIp(Map<String, dynamic> ip) async { await hh.saveToBox(box, 'ip', ip); } ... Map<String, dynamic> getDataIp() { Map<String, dynamic> map = {}; // ip resulting a _Map<dynamic, dynamic> final ip = hh.getFrombox(box, 'ip'); if (ip != null) { // with only using jsonDecode() gives error type "'_Map<dynamic, dynamic>' is not a subtype of type 'String'" // below gives error "Converting object to an encodable object failed: Instance of 'DateTime'" map = Map<String, dynamic>.from(jsonDecode(jsonEncode(ip))); } return map; } ... ... ... final data = Data(id: 1, name: "item", date: "2023-07-17T10:45:40.070Z"); await saveDataIp(data.toJson()); final dataBox = getDataIp();
解决方案
1. 直接类型转换(适用于无特殊类型的Map)
如果Map中没有DateTime这类无法直接序列化的特殊类型,可直接通过类型转换解决:
Map<String, dynamic> getDataIp() { final ip = hh.getFrombox(box, 'ip'); if (ip != null) { // 直接转换为目标类型 return (ip as Map).cast<String, dynamic>(); // 或使用Map.from构造 // return Map<String, dynamic>.from(ip as Map); } return {}; }
2. 修复DateTime序列化问题
报错提示Instance of 'DateTime',说明data.toJson()返回的Map中实际包含DateTime对象(而非字符串),导致jsonEncode()无法处理。需修改Data类的toJson()方法,将DateTime转为可序列化的字符串:
class Data { final int id; final String name; final DateTime date; Data({required this.id, required this.name, required this.date}); Map<String, dynamic> toJson() { return { 'id': id, 'name': name, // 将DateTime转为ISO标准字符串 'date': date.toIso8601String(), }; } }
修改后即可正常使用JSON序列化方法:
Map<String, dynamic> getDataIp() { Map<String, dynamic> map = {}; final ip = hh.getFrombox(box, 'ip'); if (ip != null) { map = jsonDecode(jsonEncode(ip)) as Map<String, dynamic>; } return map; }
3. 使用Hive TypeAdapter(推荐方案)
Hive原生支持自定义类型存储,无需手动转JSON,从根源避免类型丢失问题:
- 添加依赖到
pubspec.yaml:
dependencies: hive: ^2.2.3 hive_flutter: ^1.1.0 dev_dependencies: hive_generator: ^1.1.5 build_runner: ^2.1.11
- 为
Data类添加Hive注解:
import 'package:hive/hive.dart'; part 'data.g.dart'; @HiveType(typeId: 0) class Data extends HiveObject { @HiveField(0) final int id; @HiveField(1) final String name; @HiveField(2) final DateTime date; Data({required this.id, required this.name, required this.date}); }
- 运行生成命令生成Adapter:
flutter pub run build_runner build
- 注册Adapter并直接存储/读取
Data对象:
// 初始化时注册Adapter Hive.registerAdapter(DataAdapter()); // 存储方法 Future<void> saveData(Data data) async { final box = await Hive.openBox('boxip'); await box.put('data', data); } // 获取方法 Data? getData() { final box = Hive.box('boxip'); return box.get('data'); }
此方法无需手动处理Map类型转换,Hive会保留对象的强类型信息,取出时直接得到Data实例,稳定性更高。
内容的提问来源于stack exchange,提问作者pras
相关产品推荐
相关产品推荐

