Dart/Flutter中Map的正确序列化与反序列化及问题排查
Dart中Map与JSON序列化/反序列化的问题排查与修复
嘿,我来帮你拆解下你遇到的这个序列化报错问题,还有fromJson里的隐藏bug~
一、为啥调用MapTest.toJson()会炸?
你在MapTest.toJson()里直接对_mapHell用了jsonEncode(_mapHell),这踩了两个坑:
- JSON不认非字符串的键:你的
_mapHell是Map<int, SimpleData>,键是整数,但JSON规范里对象的键必须是字符串,jsonEncode碰到这种键直接懵圈,就抛出了那个Converting object to an encodable object failed的错误。 - 多此一举的嵌套编码:
toJson()方法本来就是给jsonEncode用的——jsonEncode会自动调用对象的toJson()拿到可序列化的结构,你提前把_mapHell编码成字符串塞进去,相当于给jsonEncode递了个已经打包好的包裹,它反而不知道怎么处理了(而且完全没必要)。
二、fromJson()里的坑也不小
你写的_mapHell = jsonDecode(json['coworkers']);有两个致命问题:
- 类型对不上:
jsonDecode出来的是Map<String, dynamic>(因为JSON键都是字符串),但你的_mapHell是Map<int, SimpleData>,直接赋值肯定报错。 - 没转成自定义对象:
jsonDecode后的Map里的值是原始的数字和字符串,不是SimpleData实例,你得手动把这些原始数据转换成你要的类对象才行。
三、修复后的完整代码
1. SimpleData类(基础逻辑没问题,稍微优化下可读性)
class SimpleData { int _blah; String _str; SimpleData([this._blah, this._str]); // 从JSON反序列化 SimpleData.fromJson(Map<String, dynamic> json) { _blah = json['b']; _str = json['s']; } // 序列化为JSON结构 Map<String, dynamic> toJson() => { 'b': _blah, 's': _str, }; }
2. 彻底修正的MapTest类
class MapTest { Map<int, SimpleData> _mapHell = {}; MapTest() { _mapHell[1] = SimpleData(42, "Astfgl"); _mapHell[666] = SimpleData(1234, "Vassenego"); } // 修正反序列化逻辑 MapTest.fromJson(Map<String, dynamic> json) { // 先把JSON字符串解码成字符串键的Map final decodedMap = jsonDecode(json['coworkers']) as Map<String, dynamic>; // 逐个把键转成int,值转成SimpleData实例 decodedMap.forEach((key, value) { _mapHell[int.parse(key)] = SimpleData.fromJson(value as Map<String, dynamic>); }); } // 修正序列化逻辑 Map<String, dynamic> toJson() => { // 把int键转成字符串,让SimpleData自动调用toJson 'coworkers': _mapHell.map((key, value) => MapEntry(key.toString(), value)), }; }
3. 测试一下看看效果
import 'dart:convert'; void main() { // 序列化测试 final mapTest = MapTest(); final jsonString = jsonEncode(mapTest); print(jsonString); // 输出标准的JSON字符串 // 反序列化测试 final decodedMapTest = MapTest.fromJson(jsonDecode(jsonString)); print(decodedMapTest._mapHell[1]?._str); // 输出 "Astfgl" print(decodedMapTest._mapHell[666]?._blah); // 输出 1234 }
核心优化点说明
- 序列化时处理Map键:用
map方法把int键转成字符串,既符合JSON规范,又能让jsonEncode自动调用SimpleData的toJson()方法处理值。 - 反序列化时手动转换:先解码JSON字符串,再逐个处理键和值,把字符串键转成int,把原始JSON对象转成
SimpleData实例。 - 去掉多余的
jsonEncode/jsonDecode:让toJson()只返回待序列化的结构,交给jsonEncode统一处理,避免重复编码的混乱。
内容的提问来源于stack exchange,提问作者SePröbläm
相关产品推荐
相关产品推荐

