I am trying to learn flutter but I am stuck at JSON serialization. I was following some tutorials in YouTube and from the flutter docs, but I am having a bit of hard time with the Serialization. Could you please help me a little bit, this is for educational purpose, so I am more interested in the theory behind rather than a solution in itself, however even with only the solution I think I can try to understand the process. I should mention that I am aware of this, but in my case I have nested objects in the data and that is confusing me.
Sample of response data, it is basically a shop that for each day they have a list of days when they are opened, and for each object (day) they have the open time and date.
{
"data": [
{
"openTime": {
"open": "10:00",
"close": "20:00"
},
"date": {
"gregorian": {
"day": "01",
"weekday": {
"en": "Friday",
"de": "Freitag"
},
"month": {
"number": 5,
"en": "May",
"de": "Mai"
},
"year": "2020"
}
}
},
{
"openTime": {
"open": "12:00",
"close": "18:00"
},
"date": {
"gregorian": {
"day": "02",
"weekday": {
"en": "Saturday",
"de": "Samstag"
},
"month": {
"number": 5,
"en": "May",
"de": "Mai"
},
"year": "2020"
}
}
}
]
}
My function that fetch the data:
Future<Mall> fetchData() async {
final response = await http.get(url);
if (response.statusCode == 200) {
return Mall.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load data!');
}
}
The class Mall in my case has the openTime
and date
, which I think where my problem is.
class Mall {
final dynamic openTime;
final dynamic date;
Mall({this.openTime, this.date});
factory Mall.fromJson(Map<String, dynamic> json) {
return Mall(openTime: json['openTime'], date: json['date']);
}
}
The result that I am trying to produce should be look something like this so I can iterate through the list of the data and built a card for a number of days (e.g last 7 days)
var time = [
{
"openTime": {"open": "10:00", "close": "20:00"},
"date": "01 May 2020"
},
{
"openTime": {"open": "12:00", "close": "18:00"},
"date": "02 May 2020"
},
];
The error that I get is:
type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
Please let me know if you need further details. Thanks in advance.
Solution 1: Bassem Abd Allah
you have some errors in your code.
1- in this part your response is object in container object called "data"
Future<Mall> fetchData() async {
final response = await http.get(url);
if (response.statusCode == 200) {
return Mall.fromJson(json.decode(response.body)); //here
} else {
throw Exception('Failed to load data!');
}
}
2- your mall data is a nested object in 'data' so customize your mall class to be
class Mall {
List<Datum> data;
Mall({
this.data,
});
factory Mall.fromJson(Map<String, dynamic> json) => Mall(
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
OpenTime openTime;
Date date;
Datum({
this.openTime,
this.date,
});
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
openTime: OpenTime.fromJson(json["openTime"]),
date: Date.fromJson(json["date"]),
);
Map<String, dynamic> toJson() => {
"openTime": openTime.toJson(),
"date": date.toJson(),
};
}
class Date {
Gregorian gregorian;
Date({
this.gregorian,
});
factory Date.fromJson(Map<String, dynamic> json) => Date(
gregorian: Gregorian.fromJson(json["gregorian"]),
);
Map<String, dynamic> toJson() => {
"gregorian": gregorian.toJson(),
};
}
class Gregorian {
String day;
Weekday weekday;
Month month;
String year;
Gregorian({
this.day,
this.weekday,
this.month,
this.year,
});
factory Gregorian.fromJson(Map<String, dynamic> json) => Gregorian(
day: json["day"],
weekday: Weekday.fromJson(json["weekday"]),
month: Month.fromJson(json["month"]),
year: json["year"],
);
Map<String, dynamic> toJson() => {
"day": day,
"weekday": weekday.toJson(),
"month": month.toJson(),
"year": year,
};
}
class Month {
int number;
String en;
String de;
Month({
this.number,
this.en,
this.de,
});
factory Month.fromJson(Map<String, dynamic> json) => Month(
number: json["number"],
en: json["en"],
de: json["de"],
);
Map<String, dynamic> toJson() => {
"number": number,
"en": en,
"de": de,
};
}
class Weekday {
String en;
String de;
Weekday({
this.en,
this.de,
});
factory Weekday.fromJson(Map<String, dynamic> json) => Weekday(
en: json["en"],
de: json["de"],
);
Map<String, dynamic> toJson() => {
"en": en,
"de": de,
};
}
class OpenTime {
String open;
String close;
OpenTime({
this.open,
this.close,
});
factory OpenTime.fromJson(Map<String, dynamic> json) => OpenTime(
open: json["open"],
close: json["close"],
);
Map<String, dynamic> toJson() => {
"open": open,
"close": close,
};
}
now you can fecch mall data as you did
Future<Mall> fetchData() async {
final response = await http.get(url);
if (response.statusCode == 200) {
return Mall.fromJson(json.decode(response.body)); //here
} else {
throw Exception('Failed to load data!');
}
}