I am creating a flutter app to display users in a list. I can fetch and print the data however I cannot display the data since I get this error Exception has occurred. _TypeError (type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>')
I used dio package to fetch the data. Here is the code used to make the api call
class DioClient {
final Dio _dio = Dio();
final _farmerUrl = 'https://retoolapi.dev/Rzl99e/farmers';
Future<Users?> getUser() async {
Users? users;
try {
Response userData = await _dio.get(_farmerUrl);
print('User Info: ${userData.data}');
users = Users.fromJson(userData.data);
} on DioError catch (e) {
if (e.response != null) {
print('Dio error!');
} else {
print('Error sending request! ' e.message);
}
}
return users;
}
}
This is the model class I use to parse the json response
List<Users> usersFromJson(String str) => List<Users>.from(json.decode(str).map((x) => Users.fromJson(x)));
String usersToJson(List<Users> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Users {
Users({
this.id,
this.bio,
this.email,
this.lastName,
this.firstName,
this.phoneNumber,
this.memberNumber,
});
int? id;
String? bio;
String? email;
String? lastName;
String? firstName;
String? phoneNumber;
String? memberNumber;
factory Users.fromJson(Map<String, dynamic> json) => Users(
id: json["id"],
bio: json["bio"],
email: json["email"],
lastName: json["last_name"],
firstName: json["first_name"],
phoneNumber: json["phone_number"],
memberNumber: json["member_number"],
);
Map<String, dynamic> toJson() => {
"id": id,
"bio": bio,
"email": email,
"last_name": lastName,
"first_name": firstName,
"phone_number": phoneNumber,
"member_number": memberNumber,
};
}
This is the code I am using to display the list of users
body: SingleChildScrollView(
child: Center(
child: FutureBuilder<Users?>(
future: _client.getUser(),
builder: (context, snapshot) {
if (snapshot.hasData) {
Users? userInfo = snapshot.data;
if (userInfo != null) {
return ListTile(
title: Text(userInfo.firstName! ' ' userInfo.lastName!),
subtitle: Text(userInfo.phoneNumber!),
);
}
}
return CircularProgressIndicator();
},
),
),
),
What can I change so as to fully display the user list.
CodePudding user response:
API returns JSON array not json object so that is List not Map.
i.e. User json is first element of Json Array.
So to get first element use first index. Inside fetch Info update
return Users.fromJson(jsonresponse[0]);
CodePudding user response:
Decode your data and store it in list format because your API return list data
return UserRes.fromJsonMap(jsonDecode(userData.data));
Create response class for user list
class UserRes{
List<Users> content;
UserRes.fromJsonMap(dynamic data)
: content = List<Users>.from(
data.map((sat) => Users.fromJson(sat)));
}
And call API like and your future will return list response:
final _farmerUrl = 'https://retoolapi.dev/Rzl99e/farmers';
Future<UserRes> getUser() async {
try {
Response userData = await _dio.get(_farmerUrl);
print('User Info: ${userData.data}');
return UserRes.fromJsonMap(jsonDecode(userData.data));
} on DioError catch (e) {
if (e.response != null) {
print('Dio error!');
} else {
print('Error sending request! ' e.message);
}
}
}
you can call from UI
body: SingleChildScrollView(
child: Center(
child: FutureBuilder<Users?>(
future: _client.getUser(),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Users>? userInfo = snapshot.data;
if (userInfo != null) {
return ListTile( // your data is list format you can bind with listBuilder
title: Text(userInfo.first.firstName! ' ' userInfo.first.lastName!),
subtitle: Text(userInfo.first.phoneNumber!),
);
}
}
return CircularProgressIndicator();
},
),
),
),