Home > Mobile >  Getting error of type 'List<dynamic>' is not a subtype of type 'Map<String,
Getting error of type 'List<dynamic>' is not a subtype of type 'Map<String,

Time:10-13

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();
            },
          ),
        ),
      ),
  • Related