将 Firebase 实时数据库 json 响应从 _InternalLinkedHashMap 转换为 Map

2024-05-01

I have a database in my Firebase Realtime database with children that look like this: enter image description here

以下是我在 Flutter 应用程序中通过 firebase 调用收到的 JSON:

{
  "gameAnalytics" : {
    "log" : {
      "20210926073039AbMc4uSXywqpK9OcusSV" : {
        "cityID" : "newYork",
        "countryCode" : "USA",
        "gameID" : "20210927065000Upper90IndnewYofootbiGZYy",
        "gamePaymentMethod" : "payAtPitch",
        "players" : {
          "umZ5ezrtI6a3UoCDWFDc3hInoNA2" : {
            "pnam" : "Mario Rest",
            "url" : "https://i.ibb.co/blahblah.jpg"
          }
        },
        "sportID" : "football",
        "status" : {
          "202109261130395laHd8h77R" : "completing, send back",
          "20210926113039BcUQ8RdbHs" : "payAtPitch",
          "20210926113039Ck9JsD1uf1" : "playersAdded"
        },
        "timeAndDateString" : "20210926073039",
        "totalCost" : 999,
        "type" : "ADD",
        "userWhoAddedID" : "umZ5ezrtI6a3UoCDWFDc3hInoNA2",
        "wantsToBeOrganizer" : true
      },
      "202109261146540focIuCQRi3wNfSluvkl" : {
        "cityID" : "newYork",
        "countryCode" : "USA",
        "gameID" : "20210927065000Upper90IndnewYofootbiGZYy",
        "gamePaymentMethod" : "payByBalance",
        "players" : {
          "hOBQJtqCCNgGBVrAv2MqeaFJmdu1" : {
            "pnam" : "Seong Kang",
            "url" : "messi"
          }
        },
        "promoCodeData" : "U90qaL",
        "sportID" : "football",
        "status" : {
          "2021092615465414NXsxwW51" : "playersAdded",
          "20210926154654A60TLCmS2t" : "paidByBalance",
          "20210926154654VtYR1t4bMZ" : "completing, send back"
        },
        "timeAndDateString" : "20210926114654",
        "totalCost" : 0,
        "type" : "ADD",
        "userWhoAddedID" : "hOBQJtqCCNgGBVrAv2MqeaFJmdu1",
        "wantsToBeOrganizer" : false
      },
      "20210926204533DjF3lMCMDpvwHfsh6lQJ" : {
        "amountToRefund" : 0,
        "promoCodes" : {
          "hOBQJtqCCNgGBVrAv2MqeaFJmdu1" : "U90qaL"
        },
        "status" : {
          "20210927004533ZWGNEMX27V" : "REFUNDING: 0  null  hOBQJtqCCNgGBVrAv2MqeaFJmdu1"
        },
        "type" : "CANCEL",
        "userWhoAddedID" : "hOBQJtqCCNgGBVrAv2MqeaFJmdu1"
      }
    },
    "pitchCost" : 3500,
    "playerNumbers" : {
      "hoursBefore12" : 2,
      "hoursBefore24" : 1,
      "hoursBefore3" : 2,
      "hoursBefore36" : 1,
      "hoursBefore48" : 1,
      "hoursBefore6" : 2,
      "hoursBefore72" : 1,
      "hoursBefore96" : 1
    },
    "timings" : {
      "added" : {
        "20210917004938" : "organiserID12345",
        "20210926113040" : "umZ5ezrtI6a3UoCDWFDc3hInoNA2",
        "20210926154656" : "hOBQJtqCCNgGBVrAv2MqeaFJmdu1"
      },
      "cancelled" : {
        "20210917004939" : "playersUnCancelled",
        "20210927004522" : "playersCancelled"
      },
      "removed" : {
        "20210926113042" : "organiserID12345"
      }
    }
  },
  "gameData" : {
    "addFakePlayers" : false,
    "can" : true,
    "canAddPromoCode" : true,
    "canDes" : {
      "en" : "somedesc"
    },
    "canMes" : "blahblah.",
    "cost" : 999,
    "cur" : 2,
    "currency" : "usd",
    "dat" : "20210927065000",
    "descriptions" : {
      "en" : "blahblah"
    },
    "dur" : "60 minutes",
    "expOrg" : "",
    "gameTypes" : {
      "en" : "blahblah"
    },
    "hostConfirmed" : false,
    "hostInfo" : {
      "hostDescription" : "blahblah",
      "hostNickname" : "Mario R",
      "hostPhoto" : "https://i.ibb.co/blahblah.jpg",
      "isSuperHost" : false
    },
    "lid" : "Upper90IndoorQueensabcde739219515176663407563157034467ap0mr",
    "max" : 15,
    "mes" : "blahblah",
    "mes1" : "my disappointment",
    "mes2" : "is immessurable",
    "mes3" : "and my day",
    "payAtPitchMessage" : {
      "en" : "is ruined"
    },
    "paymentType" : "justOnline",
    "paymentsAllowed" : [ "card" ],
    "pla1" : {
      "hOBQJtqCCNgGBVrAv2MqeaFJmdu1" : {
        "pnam" : "blahblah",
        "url" : "messi"
      }
    },
    "pla2" : {
      "umZ5ezrtI6a3UoCDWFDc3hInoNA2" : {
        "organizer" : true,
        "pnam" : "Mario Rest",
        "url" : "https://i.ibb.co/blahblah.jpg"
      }
    },
    "pub" : false,
    "removalAllowed" : true,
    "showHostConfirmButton" : false,
    "spotEn" : true,
    "surl" : "https://someurl",
    "title" : {
      "en" : "ok"
    }
  },
  "mess" : {
    "-MjlDj5szZxKaDs0p3CN" : {
      "mes" : "ok",
      "tim" : "20210916204938",
      "unm" : "blahblah",
      "usi" : "XwyPhbjzeKNYVczPdCPFTG0DZbj1"
    },
    "-MjlDj6bnMvKUO76EjLE" : {
      "mes" : "ok",
      "tim" : "20210916204938",
      "unm" : "blahblah",
      "usi" : "XwyPhbjzeKNYVczPdCPFTG0DZbj1"
    },
    "-MjlDj7SeqRV0KzRzFFX" : {
      "mes" : "ok",
      "tim" : "20210916204939",
      "unm" : "bllblb",
      "usi" : "XwyPhbjzeKNYVczPdCPFTG0DZbj1"
    },
    "-MjlDj8C-p406IK8I-cb" : {
      "mes" : "msg",
      "tim" : "20210916204940",
      "unm" : "msg",
      "usi" : "XwyPhbjzeKNYVczPdCPFTG0DZbj1"
    }
  },
  "payment" : {
    "playerPaymentStatus" : {
      "hOBQJtqCCNgGBVrAv2MqeaFJmdu1" : {
        "date" : "20210927004533",
        "refundedAmount" : 0,
        "stripePaymentNotConfirmed" : true,
        "type" : "notPaidForGame",
        "userWhoAddedID" : "hOBQJtqCCNgGBVrAv2MqeaFJmdu1"
      }
    }
  },
  "userReview" : {
    "showReview" : true
  }
}

我正在尝试创建一个Map<String, dynamic>通过使用 Map.from() 来获取此响应,如下所示:

class PickUpGameItem extends StatefulWidget {
  final String gameId;

  const PickUpGameItem(this.gameId, [Key? key]) : super(key: key);

  @override
  _PickUpGameItemState createState() => _PickUpGameItemState();
}

class _PickUpGameItemState extends State<PickUpGameItem> {
  late StreamSubscription _pickUpGameDetailsStreamSub;
  PickUpGameDetails? gameDetails;

  @override
  void initState() {
    super.initState();
    _setListeners();
  }

  @override
  void deactivate() {
    _pickUpGameDetailsStreamSub.cancel();
    super.deactivate();
  }

  void _setListeners() {
    _pickUpGameDetailsStreamSub = FirebaseDatabase()
        .reference()
        .child(
            '.../gamesDetailed/${widget.gameId}/')
        .onValue
        .listen((event) {
      final detailsJson = Map<String, dynamic>.from(event.snapshot.value);
      setState(() {
        gameDetails = PickUpGameDetails.fromJson(detailsJson);
        print(gameDetails.toString());
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
      child: Row(
        children: [
          ClipRRect(
            borderRadius: BorderRadius.circular(8.0),
            child: const Image(
              fit: BoxFit.fill,
              width: 80.0,
              height: 80.0,
              image: AssetImage('assets/images/temp_city_img.jpg'),
            ),
          ),
          const SizedBox(
            width: 10,
          ),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: const [
                Text(
                  'Lorem ipsum dolor sit amet this is a test ......................................',
                  style: TextStyle(
                      color: Colors.black,
                      fontWeight: FontWeight.bold,
                      fontSize: 16),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
                SizedBox(
                  height: 10,
                ),
                Text(
                  'Lorem ipsum dolor sit amet this is a test ......................................',
                  style: TextStyle(
                      color: Colors.grey,
                      fontWeight: FontWeight.normal,
                      fontSize: 14),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ],
            ),
          ),
          const SizedBox(
            width: 10,
          ),
          Flexible(
            flex: 0,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text(
                  'Football',
                  style: TextStyle(
                      color: Colors.black,
                      fontWeight: FontWeight.bold,
                      fontSize: 16),
                ),
                const SizedBox(
                  height: 10,
                ),
                Row(
                  children: const [
                    Text(
                      '14/16',
                      style: TextStyle(
                          color: Colors.grey,
                          fontWeight: FontWeight.normal,
                          fontSize: 14),
                    ),
                    SizedBox(
                      width: 5,
                    ),
                    Icon(Icons.ac_unit)
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

当我运行该应用程序时,收到一条错误消息,指出内部链接哈希映射不是映射的子类型,并且在调用 GameAnalytics.fromJson() 时发生错误。我看过多个类似的帖子,但他们的错误提到了 _InternalLinkedHashMap 映射。为什么我的回复中使用这个链接的哈希图Object?对于键和值?

[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type '_InternalLinkedHashMap<Object?, Object?>' is not a subtype of type 'Map<String, dynamic>'

这是我的 dart 模型类:

PickUpGameDetails.dart:

class PickUpGameDetails {
  GameAnalytics? gameAnalytics;
  GameData? gameData;
  UserReview? userReview;

  PickUpGameDetails(
      {required this.gameAnalytics,
      required this.gameData,
      required this.userReview});

  PickUpGameDetails.fromJson(Map<String, dynamic> json) {
    gameAnalytics = json['gameAnalytics'] != null
        ? GameAnalytics.fromJson(json['gameAnalytics'])
        : null;
    gameData =
        json['gameData'] != null ? GameData.fromJson(json['gameData']) : null;
    userReview = json['userReview'] != null
        ? UserReview.fromJson(json['userReview'])
        : null;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (gameAnalytics != null) {
      data['gameAnalytics'] = gameAnalytics!.toJson();
    }
    if (gameData != null) {
      data['gameData'] = gameData!.toJson();
    }
    if (userReview != null) {
      data['userReview'] = userReview!.toJson();
    }
    return data;
  }
}

游戏分析.dart:

class GameAnalytics {
  late int pitchCost;
  PlayerNumbers? playerNumbers;
  Timings? timings;

  GameAnalytics(
      {required this.pitchCost,
      required this.playerNumbers,
      required this.timings});

  GameAnalytics.fromJson(Map<String, dynamic> json) {
    pitchCost = json['pitchCost'];
    playerNumbers = json['playerNumbers'] != null
        ? PlayerNumbers.fromJson(json['playerNumbers'])
        : null;
    timings =
        json['timings'] != null ? Timings.fromJson(json['timings']) : null;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['pitchCost'] = pitchCost;
    if (playerNumbers != null) {
      data['playerNumbers'] = playerNumbers!.toJson();
    }
    if (timings != null) {
      data['timings'] = timings!.toJson();
    }
    return data;
  }
}

PlayerNumbers.dart:

class PlayerNumbers {
  late int hoursBefore12;
  late int hoursBefore24;
  late int hoursBefore3;
  late int hoursBefore36;
  late int hoursBefore48;
  late int hoursBefore6;
  late int hoursBefore72;
  late int hoursBefore96;

  PlayerNumbers(
      {required this.hoursBefore12,
      required this.hoursBefore24,
      required this.hoursBefore3,
      required this.hoursBefore36,
      required this.hoursBefore48,
      required this.hoursBefore6,
      required this.hoursBefore72,
      required this.hoursBefore96});

  PlayerNumbers.fromJson(Map<String, dynamic> json) {
    hoursBefore12 = json['hoursBefore12'];
    hoursBefore24 = json['hoursBefore24'];
    hoursBefore3 = json['hoursBefore3'];
    hoursBefore36 = json['hoursBefore36'];
    hoursBefore48 = json['hoursBefore48'];
    hoursBefore6 = json['hoursBefore6'];
    hoursBefore72 = json['hoursBefore72'];
    hoursBefore96 = json['hoursBefore96'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['hoursBefore12'] = hoursBefore12;
    data['hoursBefore24'] = hoursBefore24;
    data['hoursBefore3'] = hoursBefore3;
    data['hoursBefore36'] = hoursBefore36;
    data['hoursBefore48'] = hoursBefore48;
    data['hoursBefore6'] = hoursBefore6;
    data['hoursBefore72'] = hoursBefore72;
    data['hoursBefore96'] = hoursBefore96;
    return data;
  }
}

计时.dart:

class Timings {
  Map<String, dynamic>? added;
  Map<String, dynamic>? cancelled;
  Map<String, dynamic>? removed;

  Timings(
      {required this.added, required this.cancelled, required this.removed});

  Timings.fromJson(Map<String, dynamic> json) {
    added = json['added'];
    cancelled = json['cancelled'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    if (added != null) {
      data['added'] = added;
    }
    if (cancelled != null) {
      data['cancelled'] = cancelled;
    }
    if (removed != null) {
      data['removed'] = removed;
    }
    return data;
  }
}

用户评论.dart:

class UserReview {
  bool? showReview;

  UserReview({required this.showReview});

  UserReview.fromJson(Map<String, dynamic> json) {
    showReview = json['showReview'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['showReview'] = showReview;
    return data;
  }
}

游戏数据.dart:

class GameData {
  late bool addFakePlayers;
  late bool hasBeenCancelled;
  late bool canAddPromoCode;
  late String cancellationDescription;
  late String cancellationMsg;
  late int cost;
  late int cur;
  late String currency;
  late String dateTime;
  late String description;
  late String durationMsg;
  late String expOrg;
  late String gameTypeMsg;
  late bool hostConfirmed;
  late String lid;
  late int maxPlayers;
  late List<String> messages;
  late String payAtPitchMessage;
  late String paymentType;
  late List<String> paymentsAllowed;
  Team? team1;
  Team? team2;
  late bool pub;
  late bool removalAllowed;
  late bool showHostConfirmButton;
  late bool spotEn;
  late String surl;
  late String title;

  GameData(
      {required this.addFakePlayers,
      required this.hasBeenCancelled,
      required this.canAddPromoCode,
      required this.cancellationDescription,
      required this.cancellationMsg,
      required this.cost,
      required this.cur,
      required this.currency,
      required this.dateTime,
      required this.description,
      required this.durationMsg,
      required this.expOrg,
      required this.gameTypeMsg,
      required this.hostConfirmed,
      required this.lid,
      required this.maxPlayers,
      required this.messages,
      required this.payAtPitchMessage,
      required this.paymentType,
      required this.paymentsAllowed,
      required this.team1,
      required this.team2,
      required this.pub,
      required this.removalAllowed,
      required this.showHostConfirmButton,
      required this.spotEn,
      required this.surl,
      required this.title});

  GameData.fromJson(Map<String, dynamic> json) {
    addFakePlayers = json['addFakePlayers'];
    hasBeenCancelled = json['can'];
    canAddPromoCode = json['canAddPromoCode'];
    cancellationDescription = json['canDes']['en'];
    cancellationMsg = json['canMes'];
    cost = json['cost'];
    cur = json['cur'];
    currency = json['currency'];
    dateTime = json['dat'];
    description = json['descriptions']['en'];
    durationMsg = json['dur'];
    expOrg = json['expOrg'];
    gameTypeMsg = json['gameTypes']['en'];
    hostConfirmed = json['hostConfirmed'];
    lid = json['lid'];
    maxPlayers = json['max'];
    messages.add(json['mes']);
    messages.add(json['mes1']);
    messages.add(json['mes2']);
    messages.add(json['mes3']);
    payAtPitchMessage = json['payAtPitchMessage']['en'];
    paymentType = json['paymentType'];
    paymentsAllowed = json['paymentsAllowed'].cast<String>();
    team1 = json['pla1'] != null ? Team.fromJson(json['pla1']) : null;
    team2 = json['pla2'] != null ? Team.fromJson(json['pla2']) : null;
    pub = json['pub'];
    removalAllowed = json['removalAllowed'];
    showHostConfirmButton = json['showHostConfirmButton'];
    spotEn = json['spotEn'];
    surl = json['surl'];
    title = json['title']['en'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['addFakePlayers'] = addFakePlayers;
    data['can'] = hasBeenCancelled;
    data['canAddPromoCode'] = canAddPromoCode;
    data['canDes'] = cancellationDescription;
    data['canMes'] = cancellationMsg;
    data['cost'] = cost;
    data['cur'] = cur;
    data['currency'] = currency;
    data['dat'] = dateTime;
    data['descriptions'] = description;
    data['dur'] = durationMsg;
    data['expOrg'] = expOrg;
    data['gameTypes'] = gameTypeMsg;
    data['hostConfirmed'] = hostConfirmed;
    data['lid'] = lid;
    data['max'] = maxPlayers;
    data['mes'] = messages.elementAt(0);
    data['mes1'] = messages.elementAt(1);
    data['mes2'] = messages.elementAt(2);
    data['mes3'] = messages.elementAt(3);
    data['payAtPitchMessage'] = payAtPitchMessage;
    data['paymentType'] = paymentType;
    data['paymentsAllowed'] = paymentsAllowed;
    data['pla1'] = team1?.toJson();
    data['pla2'] = team2?.toJson();
    data['pub'] = pub;
    data['removalAllowed'] = removalAllowed;
    data['showHostConfirmButton'] = showHostConfirmButton;
    data['spotEn'] = spotEn;
    data['surl'] = surl;
    data['title'] = title;
    return data;
  }
}

团队.dart:

class Team {
  Map<String, Player> players;

  Team({required this.players});

  factory Team.fromJson(Map<String, dynamic> json) {
    Map<String, Player> _players = {};
    for (String key in json.keys) {
      _players[key] = Player.fromJson(json[key]);
    }
    return Team(players: _players);
  }

  Map<String, dynamic> toJson() {
    Map<String, dynamic> json = <String, dynamic>{};
    for (String key in players.keys) {
      json[key] = players[key];
    }
    return json;
  }
}

玩家.dart:

class Player {
  String name;
  String url;

  Player({required this.name, required this.url});

  factory Player.fromJson(Map<String, dynamic> json) {
    return Player(name: json['pname'], url: json['url']);
  }

  Map<String, dynamic> toJson() {
    final json = <String, dynamic>{};
    json['pname'] = name;
    json['url'] = url;
    return json;
  }
}

在搜索了 Flutter 存储库上的多个 Stack 帖子和 GitHub 问题后,我发现了这条神奇的线,由于某种奇怪的原因,它是目前让事情正常运行的唯一方法。在 flutter 存储库上提出此建议的人也提到了它有多么奇怪,但我猜测 Firebase 的响应不是有效的 JSON 格式(?)。现在,如果你想要一些有用的东西,可能就是这样:

jsonDecode(jsonEncode(event.snapshot.value)));

请注意,这可能对性能不利。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 Firebase 实时数据库 json 响应从 _InternalLinkedHashMap 转换为 Map 的相关文章

随机推荐