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
相关产品推荐
相关产品推荐

