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

Dart/Flutter中Map的正确序列化与反序列化及问题排查

Dart中Map与JSON序列化/反序列化的问题排查与修复

嘿,我来帮你拆解下你遇到的这个序列化报错问题,还有fromJson里的隐藏bug~

一、为啥调用MapTest.toJson()会炸?

你在MapTest.toJson()里直接对_mapHell用了jsonEncode(_mapHell),这踩了两个坑:

  1. JSON不认非字符串的键:你的_mapHell是Map<int, SimpleData>,键是整数,但JSON规范里对象的键必须是字符串,jsonEncode碰到这种键直接懵圈,就抛出了那个Converting object to an encodable object failed的错误。
  2. 多此一举的嵌套编码: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 17:02:32