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

Flutter中如何将JSON解码为Map<DateTime, List<Task>>

解决JSON解码为LinkedHashMap<DateTime, List<Task>>的问题

核心问题梳理

你的解码逻辑存在多处错误:Task类的枚举转换缺失、fromJson工厂方法调用错误、TaskList.fromJson的遍历逻辑错误,以及读取SharedPreferences时未正确调用自定义解码方法。以下是分步修正方案:


1. 修复Task类的fromJson方法与枚举转换

原代码直接将字符串赋值给PriorityItem类型会导致类型错误,需要添加字符串转枚举的逻辑,同时修正构造函数调用方式:

class Task {
  late int taskId;
  late bool isCompleted;
  late String text;
  late PriorityItem priority;

  // 规范构造函数参数
  Task({
    required this.taskId,
    required this.isCompleted,
    required this.text,
    required this.priority,
  });

  Map<String, dynamic> toJson() => {
        "id": taskId,
        "isCompleted": isCompleted,
        "text": text,
        "priority": priority.toString(),
      };

  factory Task.fromJson(Map<String, dynamic> json) {
    // 字符串转PriorityItem枚举
    PriorityItem priority;
    switch (json["priority"]) {
      case "PriorityItem.low":
        priority = PriorityItem.low;
        break;
      case "PriorityItem.medium":
        priority = PriorityItem.medium;
        break;
      case "PriorityItem.high":
        priority = PriorityItem.high;
        break;
      default:
        priority = PriorityItem.low; // 设置默认值避免崩溃
    }

    return Task(
      taskId: json["id"],
      isCompleted: json["isCompleted"],
      text: json["text"],
      priority: priority,
    );
  }
}

enum PriorityItem {
  low,
  medium,
  high,
}

2. 修复TaskList类的fromJson方法

原代码存在初始化错误、遍历逻辑错误(错误使用json[value]),以及Task对象转换错误,修正如下:

class TaskList {
  static LinkedHashMap<DateTime, List<Task>> weeklyTaskMap = LinkedHashMap<DateTime, List<Task>>();
  static LinkedHashMap<DateTime, List<Task>> taskMap = LinkedHashMap<DateTime, List<Task>>(); // 补充原代码缺失的taskMap

  static Map<String, dynamic> toJson(LinkedHashMap<DateTime, List<Task>> taskMap) {
    Map<String, dynamic> myMap = {};
    taskMap.forEach((key, value) {
      myMap[key.toIso8601String()] = List<dynamic>.from(value.map((x) => x.toJson()));
    });
    return myMap;
  }

  static LinkedHashMap<DateTime, List<Task>> fromJson(Map<String, dynamic> json) {
    // 正确初始化LinkedHashMap,避免强制类型转换错误
    LinkedHashMap<DateTime, List<Task>> myMap = LinkedHashMap<DateTime, List<Task>>();
    json.forEach((key, value) {
      // 将JSON中的任务列表转换为List<Task>
      List<Task> tasks = List<Task>.from(
        (value as List<dynamic>).map((taskJson) => Task.fromJson(taskJson as Map<String, dynamic>)),
      );
      myMap[DateTime.parse(key)] = tasks;
    });
    return myMap;
  }
}

3. 修复getMapsFromPrefs的解码逻辑

原代码中weeklyMap直接使用jsonDecode,未调用TaskList.fromJson导致类型不匹配,修正如下:

void getMapsFromPrefs() async {
  SharedPreferences getMaps = await _prefs;

  // 先解码得到Map<String, dynamic>,再传入自定义fromJson转换
  Map<String, dynamic> dailyJson = jsonDecode(getMaps.getString('daily')!);
  Map<String, dynamic> weeklyJson = jsonDecode(getMaps.getString('weekly')!);
  
  TaskList.taskMap = TaskList.fromJson(dailyJson);
  TaskList.weeklyTaskMap = TaskList.fromJson(weeklyJson);
}

void saveMapsToPrefs() async {
  SharedPreferences getMaps = await _prefs;
  getMaps.clear();
  var dailyTasksJson = json.encode(TaskList.toJson(TaskList.taskMap));
  var weeklyTasksJson = json.encode(TaskList.toJson(TaskList.weeklyTaskMap));

  getMaps.setString('daily', dailyTasksJson);
  getMaps.setString('weekly', weeklyTasksJson);

  print("saved ${getMaps.getString('daily')}");
}

关键修正点总结

  • 枚举转换:JSON不支持枚举直接序列化/反序列化,必须手动将字符串枚举值转换为PriorityItem类型。
  • fromJson逻辑:遍历JSON时直接使用value(对应日期键下的任务列表),而非错误的json[value];正确初始化LinkedHashMap,避免强制类型转换导致的错误。
  • 解码流程:从SharedPreferences读取的JSON字符串,必须先通过jsonDecode得到Map<String, dynamic>,再传入TaskList.fromJson转换为目标类型,不能直接赋值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 13:15:34