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

Dart中如何从序列化Map正确反序列化自定义类对象

如何从经过序列化/反序列化处理的对象Map中重新创建自定义类实例?

复现代码

import 'dart:convert';

class InternalTx {
  int a;
  bool b;

  InternalTx(this.a, this.b);

  factory InternalTx.fromJson(Map<String, dynamic> json) =>
      InternalTxFromJson(json);

  Map<String, dynamic> toJson() => InternalTxToJson(this);
}

InternalTx InternalTxFromJson(Map<String, dynamic> json) => InternalTx(
      json['a'] as int,
      json['b'] as bool,
    );

Map<String, dynamic> InternalTxToJson(InternalTx instance) => <String, dynamic>{
      'a': instance.a,
      'b': instance.b,
    };

main() {
  Map<String, InternalTx> m = {};
  for (int i=0; i<10; i++)
  {
    InternalTx itx = InternalTx(i, false);
    m["Hello: $i"] = itx;
  }
  
  String serM = jsonEncode(m);
  print(serM);
  
  ////SERILIZED OKAY
  
  Map<String, dynamic> n = jsonDecode(serM);
  InternalTx newItx = n["Hello: 0"];      // 此处抛出错误
  print(newItx);
}

运行报错输出

{"Hello: 0":{"a":0,"b":false},"Hello: 1":{"a":1,"b":false},"Hello: 2":{"a":2,"b":false},"Hello: 3":{"a":3,"b":false},"Hello: 4":{"a":4,"b":false},"Hello: 5":{"a":5,"b":false},"Hello: 6":{"a":6,"b":false},"Hello: 7":{"a":7,"b":false},"Hello: 8":{"a":8,"b":false},"Hello: 9":{"a":9,"b":false}}
Uncaught Error: TypeError: Instance of '_JsonMap': type '_JsonMap' is not a subtype of type 'InternalTx'

问题原因

jsonDecode 反序列化JSON字符串时,只会输出Dart内置基础类型(Map、List、字符串、数字、布尔、null),不会自动将嵌套Map转换为你定义的自定义类实例。你虽然为InternalTx实现了fromJson命名构造,但代码中从未调用该构造做类型转换,因此n["Hello: 0"]取到的是Dart内部实现的_JsonMap类型实例,直接赋值给InternalTx类型变量就会抛出类型不匹配错误。

修复方案

你需要手动调用自定义类的fromJson构造,将反序列化得到的Map转换为对应类实例,两种常用场景的写法如下:

  • 仅取单个值时,直接对取值结果做转换:
// 替换原来的错误赋值行
InternalTx newItx = InternalTx.fromJson(n["Hello: 0"] as Map<String, dynamic>);
  • 需要还原整个Map<String, InternalTx>结构时,批量遍历转换所有条目:
Map<String, dynamic> n = jsonDecode(serM);
// 批量转换所有值为InternalTx实例
Map<String, InternalTx> restoredMap = n.map(
  (key, value) => MapEntry(key, InternalTx.fromJson(value as Map<String, dynamic>))
);
// 后续从restoredMap取值就可以直接得到InternalTx类型实例
InternalTx newItx = restoredMap["Hello: 0"];

内容的提问来源于stack exchange,提问作者Defarine

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 03:09:29