I have a database in my Firebase Realtime database with children that look like this:

Here's the JSON that I receive in my Flutter app from my firebase call:
{
"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
}
}
I'm trying to create a Map<String, dynamic> from this response by using Map<String,dynamic>.from() as seen below:
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)
],
),
],
),
),
],
),
);
}
}
When I run the app, I get an error saying that the internal linked hash map isn't a subtype of map and that the error occurs when calling GameAnalytics.fromJson(). I've seen multiple similar posts but their error mentioned an _InternalLinkedHashMap<String?, dynamic> map. Why Is this linked hash map in my response using Object? for both keys and values?
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type '_InternalLinkedHashMap<Object?, Object?>' is not a subtype of type 'Map<String, dynamic>'
Here are my dart model classes:
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;
}
}
GameAnalytics.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;
}
}
Timings.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;
}
}
UserReview.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;
}
}
GameData.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;
}
}
Team.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;
}
}
Player.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;
}
}
