I'm trying to use Flutter documentation to map an array data (comes from API) to the dart object. The documentation uses a single Json object, not an array. I have the following codes:
Json data:
[
{
"channelId" : 1
"channelTitle" : "Photos"
"channelImage" : pr01.jpg
"channelLastPost" : null
"lastUpdate" : null
"userRef" : 1
},
{
"channelId" : 2
"channelTitle" : "Science"
"channelImage" : pr02.jpg
"channelLastPost" : "For test ...."
"lastUpdate" : "2023-01-03"
"userRef" : 1
}
]
ChannelListModel.dart:
class ChannelListModel {
String creator;
String? image;
String title;
String lastPost;
String lastUpdate;
ChannelListModel(
{required this.creator,
required this.image,
required this.title,
required this.lastPost,
required this.lastUpdate});
factory ChannelListModel.fromJson(Map<String, dynamic> json) {
return ChannelListModel(
creator: json['userRef'],
image: json['channelImage'],
title: json['channelTitle'],
lastPost: json['channelLastPost'],
lastUpdate: json['lastUpdate']);
}
Map<String, dynamic> toJson() {
return {
"userRef" : creator,
"channelImage" : image,
"channelTitle" : title,
"channelLastPost" : lastPost,
"lastUpdate" : lastUpdate
};
}
}
HttpRequest.dart:
class HttpServices {
Future<List<ChannelListModel>> getChannelList() async {
var url = base.BaseURL.channelListUrl;
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return List<ChannelListModel>.fromJson(jsonDecode(response.body)); //I have problem in this line
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
}
ChannelPage.dart:
class _ChannelsState extends State<Channels> {
List<ChannelListModel> channels = [];
@override
void initState() {
super.initState();
channels = getChannelsFromHttp(); // A valid array object needs to be provided here.
}
getChannelsFromHttp()async{
var httpService = HttpServices();
var result = await httpService.getChannelList();
return result;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: channels.length,
itemBuilder: (context, index) =>
ChannelCard(channelModel: channels[index]),
),
);
}
}
I want to classify my codes so I decided to provided different dart files for each part. How can I fix my code?
CodePudding user response:
Instead of
returnList<ChannelListModel>.fromJson(jsonDecode(response.body));
Try this code,
List<ChannelListModel> channels = [];
final res = jsonDecode(response.body);
channels.addAll(List<ChannelListModel>.from(
(res).map((x) => ChannelListModel.fromJson(x))));
return channels;
Added based on comments
@override
void initState() {
super.initState();
getChannelsFromHttp();
}
getChannelsFromHttp()async{
var httpService = HttpServices();
var result = await httpService.getChannelList();
setState((){
channels = result;
});
}
CodePudding user response:
Your fromJson
factory returns single ChannelListModel
.
You can't use List<ChannelListModel>.fromJson
. Instead iterate through List
and convert each json
to ChannelListModel
class HttpServices {
Future<List<ChannelListModel>> getChannelList() async {
var url = base.BaseURL.channelListUrl;
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
//return List<ChannelListModel>.fromJson(jsonDecode(response.body));
final data = jsonDecode(response.body) as List<dynamic>;
return data.map((e) => ChannelListModel.fromJson(e as Map<String, dynamic>))
.toList();
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
}
CodePudding user response:
You can modify the ChannelListModel.fromJson method to handle a list of JSON objects instead of a single object. Here's one way to do it:
factory ChannelListModel.fromJson(List<dynamic> jsonList) {
return jsonList.map((json) => ChannelListModel(
creator: json['userRef'],
image: json['channelImage'],
title: json['channelTitle'],
lastPost: json['channelLastPost'],
lastUpdate: json['lastUpdate'])
).toList();
}
You can also use jsonDecode to convert the response body to a List and then use the above method to convert the list to ChannelListModel
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
final jsonData = jsonDecode(response.body);
return ChannelListModel.fromJson(jsonData);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
Also, you need to update the getChannelsFromHttp function to assign the result of httpService.getChannelList() to channels variable instead of calling the function again.
@override
void initState() {
super.initState();
getChannelsFromHttp();
}
getChannelsFromHttp() async {
var httpService = HttpServices();
channels = await httpService.getChannelList();
setState(() {});
}
This should solve the problem in your code.