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

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自动生成序列化代码,可以自定义类型转换器处理特殊类型,避免手写重复逻辑:

  1. 先定义两个自定义转换器,分别处理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()));
  }
}
  1. 给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);
}
  1. 执行命令flutter pub run build_runner build即可自动生成序列化代码,无需手写转换逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 17:57:03