Flutter嵌套类DilemmData序列化保存报错,寻求正确实现方案
问题分析与解决方案
核心问题
- 序列化失败:
DilemmData仅定义了静态toJson方法,jsonEncode无法自动识别并调用,导致无法将实例转换为JSON可编码对象。 - 嵌套对象未正确反序列化:
DilemmData.fromJson中直接将json['plus']/json['minus']传入构造函数,未将JSON数组转换为List<DilemmItemData>实例。 - 数据结构不匹配:保存单个
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
相关产品推荐
相关产品推荐

