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

Flutter嵌套类DilemmData序列化保存报错,寻求正确实现方案

问题分析与解决方案

核心问题

  1. 序列化失败:DilemmData仅定义了静态toJson方法,jsonEncode无法自动识别并调用,导致无法将实例转换为JSON可编码对象。
  2. 嵌套对象未正确反序列化:DilemmData.fromJson中直接将json['plus']/json['minus']传入构造函数,未将JSON数组转换为List<DilemmItemData>实例。
  3. 数据结构不匹配:保存单个DilemmData实例,但加载时试图强制转换为List<DilemmData>,导致类型错误。

修正后的完整代码

1. 修复DilemmData与DilemmItemData的序列化逻辑

class DilemmData {
  double percent = 0;
  final String title;
  final String date;
  List<DilemmItemData> plus = [];
  List<DilemmItemData> minus = [];

  // 构造函数指定参数类型,避免类型歧义
  DilemmData(
    this.plus,
    this.minus, {
    this.percent = 0,
    this.title = '',
    this.date = '',
  });

  // 将静态toJson改为实例方法,让jsonEncode自动调用
  Map<String, dynamic> toJson() {
    return {
      'percent': percent,
      'title': title,
      'date': date,
      'plus': plus.map((e) => e.toJson()).toList(),
      'minus': minus.map((e) => e.toJson()).toList(),
    };
  }

  factory DilemmData.fromJson(Map<String, dynamic> json) {
    // 将JSON数组转换为List<DilemmItemData>
    final plusList = (json['plus'] as List<dynamic>)
        .map((item) => DilemmItemData.fromJson(item as Map<String, dynamic>))
        .toList();
    final minusList = (json['minus'] as List<dynamic>)
        .map((item) => DilemmItemData.fromJson(item as Map<String, dynamic>))
        .toList();

    return DilemmData(
      plusList,
      minusList,
      percent: json['percent'] as double,
      title: json['title'] as String,
      date: json['date'] as String,
    );
  }

  // 保留列表序列化/反序列化工具方法
  static String encode(List<DilemmData> dilemms) => json.encode(
        dilemms.map((dil) => dil.toJson()).toList(),
      );

  static List<DilemmData> decode(String dilemmsJson) =>
      ((json.decode(dilemmsJson) ?? []) as List<dynamic>)
          .map((dil) => DilemmData.fromJson(dil as Map<String, dynamic>))
          .toList();
}

class DilemmItemData {
  final int importance;
  final String argument;

  DilemmItemData({this.importance = 0, this.argument = ''});

  Map<String, dynamic> toJson() {
    return {
      'importance': importance,
      'argument': argument,
    };
  }

  factory DilemmItemData.fromJson(Map<String, dynamic> json) {
    return DilemmItemData(
      importance: json['importance'] as int,
      argument: json['argument'] as String,
    );
  }
}

2. 修复保存函数(保存整个列表)

// 先将新实例添加到现有列表
MyApp.dilemmList.add(DilemmData(
  [], // 初始化空的plus列表
  [], // 初始化空的minus列表
  percent: 0,
  title: controller.text,
  date: clockString,
));

SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
// 使用DilemmData.encode序列化整个列表
String data = DilemmData.encode(MyApp.dilemmList);
sharedPreferences.setString('dilemms', data);

3. 修复加载函数

Future loadDillems() async {
  SharedPreferences sharedPreferences = await SharedPreferences.getInstance();

  if (sharedPreferences.containsKey('dilemms')) {
    String? jsonString = sharedPreferences.getString('dilemms');
    if (jsonString != null) {
      // 使用DilemmData.decode直接解析为List<DilemmData>
      MyApp.dilemmList = DilemmData.decode(jsonString);
    }
  }
}

关键说明

  • 实例级toJson方法是jsonEncode能自动序列化对象的前提,静态方法无法被框架自动调用。
  • 反序列化嵌套对象时,必须手动将JSON数组转换为对应类型的实例列表,不能直接传入原始JSON数据。
  • 保存与加载的数据结构必须一致:如果要保存列表,就用工具方法序列化/反序列化列表,避免单个实例与列表的类型冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 11:54:20