Flutter如何解决GetStorage写入对象报encodable object failed异常
异常原因
- GetStorage 写入数据时默认调用 Dart 内置的
jsonEncode做序列化,这个方法原生只支持数字、字符串、布尔、列表、键为字符串的Map这类基础结构,无法直接识别自定义类实例。 - 定义的
Mesure、DataBase两个类没有提供转可编码Map结构的序列化方法,直接传入实例时序列化流程无法执行,就会抛出「对象无法转成可编码对象」的异常。 - 额外注意:原有
DataBase.init构造函数存在隐藏bug,入参名和类成员属性名完全一致时,不加this.前缀的赋值只会修改临时入参的值,不会给类的成员属性赋值,后续读属性会触发late未初始化错误,这个问题需要同步修复。
解决方法
第一步:修改两个自定义类,修复构造bug+添加序列化方法
首先修改Mesure类,新增toJson方法把对象转成可被jsonEncode识别的Map结构:
class Mesure { late String equipement; late String number; late String courant = ""; Mesure.init(List<String> values) { equipement = values[0]; number = values[1]; courant = values[2]; } // 新增序列化方法 Map<String, dynamic> toJson() { return { "equipement": equipement, "number": number, "courant": courant, }; } }
再修改DataBase类,修复构造函数赋值问题,同时新增对应的toJson方法,嵌套调用Mesure的序列化方法:
class DataBase { late int? id; late Mesure? mesure; late String? status; // 修复构造函数:给属性赋值加this.前缀,明确指向类成员 DataBase.init(int id, Mesure mesure, String status) { this.id = id; this.mesure = mesure; this.status = status; } // 新增序列化方法 Map<String, dynamic> toJson() { return { "id": id, "mesure": mesure?.toJson(), "status": status, }; } }
第二步:写入存储时传入序列化后的Map
不要直接传自定义类实例,调用实例的toJson()方法转成Map后再写入:
Mesure mesure = Mesure.init(values); DataBase test = DataBase.init(0, mesure, "status"); final box = GetStorage(); box.write('data', test.toJson());
第三步:读取数据时反序列化为自定义实例
从GetStorage读出来的值是Map类型,需要手动解析还原成DataBase实例,不能直接把读取结果强转成自定义类:
final storedMap = box.read('data'); if (storedMap != null) { // 先解析嵌套的Mesure对象 final mesureMap = storedMap['mesure']; final storedMesure = Mesure.init([ mesureMap['equipement'], mesureMap['number'], mesureMap['courant'], ]); // 组装成完整的DataBase实例 final storedData = DataBase.init( storedMap['id'], storedMesure, storedMap['status'], ); // 后续直接使用storedData即可 }
如果类的字段很多,手写toJson/fromJson容易出错,可以引入json_serializable等代码生成库自动生成序列化逻辑,简单场景下手动写上述方法就足够用。
内容的提问来源于stack exchange,提问作者Abmb
相关产品推荐
相关产品推荐

