Dart jsonEncode报错:无法将Product实例转换为可JSON编码对象
问题根因
Dart 内置的jsonEncode方法默认仅支持序列化基础类型(数字、字符串、布尔值、null),以及由上述类型构成的List、Map结构,遇到自定义类实例时会直接抛出你遇到的Converting object to an encodable object failed异常。
你的代码存在两处直接触发报错的问题:
ShoppingListProduct的toJson方法中,直接将Product类型的自定义类实例放入序列化Map,未调用Product类自带的toJson方法转换为可序列化的Map结构,jsonEncode遍历到Product实例时无法识别直接报错。Product类中productPrices字段声明为Map<Retailers, double>,键为自定义的Retailers类型(枚举/自定义类),不符合JSON仅支持字符串键的规范,就算修复前一个问题,该字段也会触发序列化失败;同时反序列化时直接将jsonDecode返回的Map强转为Map<Retailers, double>也会报错,因为jsonDecode输出的Map键永远是String类型。
修复步骤
1. 修正ShoppingListProduct的toJson嵌套序列化
将Product实例手动调用toJson转换后再放入Map:
Map<String, dynamic> toJson() { return { 'ID': ID, 'product': product.toJson(), // 替换原来直接传product的写法 'ticked': ticked, }; }
2. 修正productPrices字段的序列化/反序列化逻辑
JSON格式的Map键仅支持字符串类型,你需要对自定义类型的键做双向转换:
如果Retailers是枚举类型,修改代码如下:
// Product类toJson方法修改 Map<String, dynamic> toJson(){ return { 'user': user, 'id': id, 'name': name, 'image': image, 'brandName': brandName, // 将枚举键转为字符串存储,通过枚举自带的name属性获取字符串标识 'productPrices': productPrices.map((key, value) => MapEntry(key.name, value)), }; } // Product类fromJson构造方法修改 Product.fromJson(Map<String, dynamic> map) : user = (map['user'] as String), id = (map['id'] as num).toInt(), // 改成num转int,兼容double类型的数值存储 name = (map['name'] as String), image = (map['image'] as String), brandName = (map['brandName'] as String), // 先读取String键的Map,再将字符串键转回对应枚举值 productPrices = (map['productPrices'] as Map<String, dynamic>).map( (key, value) => MapEntry( Retailers.values.byName(key), (value as num).toDouble(), // 兼容int类型的数值存储 ) );
如果Retailers是普通自定义类,需要给该类也实现对应的toJson、fromJson方法,选取类的唯一字符串标识作为Map键做双向转换。
3. 其他逻辑bug修复
- 你的Product类重写Equatable的props时遗漏了
user字段,会导致实例相等判断失效,后续删除、更新购物清单商品时会出现匹配错误,把user加入props列表即可。 - 反序列化时的类型强转建议都加num类型兼容,避免本地存储/接口返回的数值类型不匹配(比如int存成double)导致的强转报错。
内容的提问来源于stack exchange,提问作者Jack .T
相关产品推荐
相关产品推荐

