Flutter(Dart)中含Map<String,Set>的类如何实现JSON序列化与反序列化
核心思路
JSON原生仅支持String、数字、布尔、数组、对象、null这几类基础类型,所以你定义的Profile类里有两个特殊字段需要单独处理:
_id类型为DatabaseReference,如果不需要序列化可以直接忽略,需要序列化的话可以转成它对应的path字符串存储attrs里的值是Set,序列化时转成List,反序列化时再转回来即可
注意:你给出的attrs示例格式是
List<Map>,和类定义的Map<String, Set>不符,下面方案默认按类定义的Map结构实现,如果实际是List类型,对应调整转换逻辑即可。
方案1:手动实现toJson/fromJson
适合小项目或者不想引入额外生成代码依赖的场景:
import 'dart:convert'; import 'package:firebase_database/firebase_database.dart'; class Profile { DatabaseReference? _id; String userId; Map<String, Set> attrs; Profile({ DatabaseReference? id, required this.userId, required this.attrs, }) : _id = id; // 序列化方法 Map<String, dynamic> toJson() { return { // 如果不需要序列化_id可以直接删掉这行 'id': _id?.path, 'userId': userId, 'attrs': attrs.map((key, value) => MapEntry(key, value.toList())), }; } // 反序列化方法 factory Profile.fromJson(Map<String, dynamic> json) { // 把attrs里的每个List转回Set Map<String, dynamic> attrsJson = json['attrs']; Map<String, Set> attrs = attrsJson.map((key, value) => MapEntry(key, Set.from(value))); return Profile( // 如果不需要序列化_id可以直接删掉这行 id: json['id'] != null ? FirebaseDatabase.instance.ref(json['id']) : null, userId: json['userId'], attrs: attrs, ); } }
方案2:配合json_serializable实现(自定义转换器)
如果你的项目已经用json_serializable自动生成序列化代码,可以自定义类型转换器处理特殊类型,避免手写重复逻辑:
- 先定义两个自定义转换器,分别处理DatabaseReference和Map<String, Set>:
import 'package:json_annotation/json_annotation.dart'; import 'package:firebase_database/firebase_database.dart'; // DatabaseReference类型转换器 class DatabaseReferenceConverter implements JsonConverter<DatabaseReference?, String?> { const DatabaseReferenceConverter(); @override DatabaseReference? fromJson(String? path) { if (path == null) return null; return FirebaseDatabase.instance.ref(path); } @override String? toJson(DatabaseReference? ref) { return ref?.path; } } // attrs字段类型转换器 class AttrsConverter implements JsonConverter<Map<String, Set>, Map<String, dynamic>> { const AttrsConverter(); @override Map<String, Set> fromJson(Map<String, dynamic> json) { return json.map((key, value) => MapEntry(key, Set.from(value))); } @override Map<String, dynamic> toJson(Map<String, Set> attrs) { return attrs.map((key, value) => MapEntry(key, value.toList())); } }
- 给Profile类加注解,关联转换器:
part 'profile.g.dart'; @JsonSerializable() @DatabaseReferenceConverter() class Profile { // 如果不需要序列化_id,加 @JsonKey(ignore: true) 注解即可 @JsonKey(name: 'id') DatabaseReference? _id; String userId; @AttrsConverter() Map<String, Set> attrs; Profile({ DatabaseReference? id, required this.userId, required this.attrs, }) : _id = id; factory Profile.fromJson(Map<String, dynamic> json) => _$ProfileFromJson(json); Map<String, dynamic> toJson() => _$ProfileToJson(this); }
- 执行命令
flutter pub run build_runner build即可自动生成序列化代码,无需手写转换逻辑。
内容的提问来源于stack exchange,提问作者Hayato Yu
相关产品推荐
相关产品推荐

