You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,从根源避免类型丢失问题:

  1. 添加依赖到pubspec.yaml:
dependencies:
  hive: ^2.2.3
  hive_flutter: ^1.1.0

dev_dependencies:
  hive_generator: ^1.1.5
  build_runner: ^2.1.11
  1. 为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});
}
  1. 运行生成命令生成Adapter:
flutter pub run build_runner build
  1. 注册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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:38:17