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

Flutter中如何将Map<String, List<object>>存储到SharedPreferences

解决方案

报错原因说明

你遇到的两个报错均是序列化逻辑缺失导致的:

  1. 直接调用json.encode()失败:Dart 内置JSON序列化仅支持num、String、bool、List、Map、null这类基础类型,自定义类MyObj没有对应的序列化规则时,就会抛出对象转可编码结构失败的错误。
  2. 调用json.decode()格式错误:你之前存入的字符串大概率是直接调用Map的toString()生成的,这类字符串包含Instance of 'MyObj'这类非标准JSON格式的内容,解码时自然无法识别。

方案1:手动处理无需额外第三方包

步骤1:给MyObj添加序列化/反序列化方法

给自定义类补充toJson(转可序列化Map)和fromJson(从Map转回实例)方法,示例代码如下:

class MyObj {
  // 替换为你实际的类字段
  final String id;
  final int count;

  MyObj({required this.id, required this.count});

  /// 转可序列化的Map结构
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'count': count,
      // 补充所有你需要持久化的字段
    };
  }

  /// 从Map结构生成MyObj实例
  factory MyObj.fromJson(Map<String, dynamic> json) {
    return MyObj(
      id: json['id'] as String,
      count: json['count'] as int,
      // 对应上面toJson的所有字段
    );
  }
}

步骤2:存储数据

先把整个Map<String, List<MyObj>>转成全基础类型的可序列化结构,再编码为JSON字符串存入SharedPreferences:

import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';

// 你的源数据
Map<String, List<MyObj>> originalData = {
  "ExampleString": [MyObj(id: "1", count: 2), MyObj(id: "2", count: 3)],
  "ExampleString2": [MyObj(id: "3", count: 5)]
};

Future<void> saveData() async {
  final prefs = await SharedPreferences.getInstance();
  // 转换为可序列化的结构
  final serializableData = originalData.map((key, value) => MapEntry(
    key,
    value.map((obj) => obj.toJson()).toList(),
  ));
  // 编码为JSON字符串存储
  await prefs.setString('my_custom_data', json.encode(serializableData));
}

步骤3:读取数据

读取JSON字符串后解码,再逐字段转换回Map<String, List<MyObj>>结构:

Future<Map<String, List<MyObj>>?> loadData() async {
  final prefs = await SharedPreferences.getInstance();
  final jsonStr = prefs.getString('my_custom_data');
  if (jsonStr == null) return null;
  // 解码为基础类型结构
  final decodedMap = json.decode(jsonStr) as Map<String, dynamic>;
  // 转换为目标结构
  return decodedMap.map((key, value) => MapEntry(
    key,
    (value as List<dynamic>).map((item) => MyObj.fromJson(item as Map<String, dynamic>)).toList(),
  ));
}

方案2:使用第三方包简化流程

如果不想手动维护序列化逻辑,可以选择以下成熟的第三方库:

  • json_serializable:Dart官方推荐的序列化工具,配合build_runner可自动生成toJson/fromJson代码,无需手动编写,避免手写出错。
  • hive:轻量级NoSQL本地存储库,性能优于SharedPreferences,支持直接存储自定义类型,只需给自定义类注册适配逻辑即可,无需手动转JSON字符串。
  • get_storage:基于SharedPreferences封装的轻量存储库,对序列化逻辑做了封装,使用更简单,同样需要先给自定义类实现序列化规则。

内容的提问来源于stack exchange,提问作者user16712640

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 15:09:04