skip to Main Content

Trying to fetch data from an API with a GET method, but it keeps showing this error: `

"Error: type ‘Null’ is not a subtype of type ‘Map<String, dynamic>’ in
type cast"

` why? I am making use of the json_serializable and the json_annotation dart packages as seen in the code below… It keeps returning the error as shown.

// This is my class for fetching the data...
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:big_shelf/screens/models/models.dart';

class MyProfileApiServices {
  final String myProfileUrl = 'https://bigshelf-node-dev.onrender.com/api/v1/users/my-profile';

  Future<UserModel> fetchUserData() async {
    final response = await http.get(Uri.parse(myProfileUrl));
    if (response.statusCode == 200) {
      final jsonResponse = jsonDecode(response.body);
      final userData = UserModel.fromJson(jsonResponse);
      debugPrint('$userData');
      return userData;
    } else {
      debugPrint('Failed to load data');
      throw Exception('Failed to load user data');
    }
  }
}


// The below is where I want to display the data that has been fetched...
import 'widget.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../services/users/users_services.dart';
import 'package:big_shelf/screens/models/models.dart';
import 'package:big_shelf/screens/common/widget.dart';

class MyShelf extends StatefulWidget {
  const MyShelf({super.key});

  @override
  State<MyShelf> createState() => _MyShelfState();
}

class _MyShelfState extends State<MyShelf> {
  late Future<UserModel> futureUser;

  @override
  void initState() {
    super.initState();
    futureUser = MyProfileApiServices().fetchUserData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          'My Shelf',
          style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 16,
            fontFamily: 'Playfair',
          ),
        ),
        actions: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 8.0),
            child: Row(
              children: [
                IconButton(
                  onPressed: () {
                    GoRouter.of(context).go('${CustomNavigationHelper.myShelfPath}/${CustomNavigationHelper.settingsPath}');
                  },
                  icon: SvgPicture.asset(
                    'assets/icons/Settings.svg',
                    colorFilter: ColorFilter.mode(
                      Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black,
                      BlendMode.srcIn,
                    ),
                  ),
                ),
                InkWell(
                  onTap: () => GoRouter.of(context).go('${CustomNavigationHelper.myShelfPath}/${CustomNavigationHelper.notificationPath}'),
                  child: Padding(
                    padding: const EdgeInsets.all(10.0),
                    child: Stack(
                      alignment: AlignmentDirectional.topEnd,
                      children: [
                        SvgPicture.asset(
                          width: 25,
                          height: 23,
                          'assets/icons/Bell.svg',
                          colorFilter: ColorFilter.mode(
                            Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black,
                            BlendMode.srcIn,
                          ),
                        ),
                        Container(
                          padding: const EdgeInsets.all(4),
                          decoration: BoxDecoration(
                            color: Theme.of(context).primaryColor,
                            shape: BoxShape.circle,
                          ),
                          child: const Text(
                            '9',
                            style: TextStyle(
                              fontSize: 10.0,
                              color: Colors.black,
                              fontWeight: FontWeight.bold,
                            ),
                            textAlign: TextAlign.center,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
      body: FutureBuilder<UserModel>(
        future: futureUser,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            debugPrint('Error: ${snapshot.error}');
            return Center(child: Text('Error: ${snapshot.error}'));
          } else if (snapshot.hasData) {
            final user = snapshot.data!.data.user;
            return SingleChildScrollView(
              child: Column(
                children: [
                  Container(
                    alignment: Alignment.center,
                    padding: const EdgeInsets.fromLTRB(0, 20, 0, 10),
                    color: Colors.grey.withOpacity(0.1),
                    child: Column(
                      children: [
                        CircleAvatar(
                          radius: 50.0,
                          backgroundColor: Colors.grey[200],
                          backgroundImage: const AssetImage('assets/images/Profile icon.png'),
                        ),
                        const SizedBox(height: 10),
                        Text(
                          user.username,
                          style: const TextStyle(
                            fontSize: 25.0,
                            fontWeight: FontWeight.bold,
                            fontFamily: 'Playfair',
                          ),
                        ),
                        Text(
                          '${snapshot.data!.data.followersCount} followers, ${snapshot.data!.data.followingCount} following',
                          style: const TextStyle(
                            fontSize: 12.0,
                            fontWeight: FontWeight.w300,
                            fontFamily: 'Satoshi',
                          ),
                        ),
                        const SizedBox(height: 15),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 80),
                          child: ElevatedButton(
                            onPressed: () => GoRouter.of(context).go('${CustomNavigationHelper.myShelfPath}/${CustomNavigationHelper.createCollectionPath}'),
                            style: ElevatedButton.styleFrom(
                              elevation: 0,
                              backgroundColor: Colors.transparent,
                              shape: RoundedRectangleBorder(
                                side: BorderSide(
                                  color: Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black,
                                ),
                                borderRadius: BorderRadius.circular(10),
                              ),
                              minimumSize: const Size(30, 60),
                            ),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Icon(
                                  Icons.add,
                                  color: Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black,
                                ),
                                const SizedBox(width: 10),
                                Text(
                                  'Create a collection',
                                  style: TextStyle(
                                    fontWeight: FontWeight.w500,
                                    fontSize: 15.0,
                                    color: Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black,
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  const SizedBox(height: 10),
                  Container(
                    alignment: Alignment.centerLeft,
                    padding: const EdgeInsets.fromLTRB(20, 0, 0, 0),
                    child: const Text(
                      'Your Shelf',
                      style: TextStyle(
                        fontFamily: 'Satoshi',
                        fontSize: 17.0,
                        fontWeight: FontWeight.bold,
                      ),
                      textAlign: TextAlign.left,
                    ),
                  ),
                  const SizedBox(height: 10),
                  DefaultTabController(
                    length: 3,
                    child: Column(
                      children: [
                        Container(
                          padding: const EdgeInsets.all(5),
                          margin: const EdgeInsets.fromLTRB(15, 0, 15, 0),
                          decoration: BoxDecoration(
                            borderRadius: const BorderRadius.all(Radius.circular(10)),
                            color: Colors.grey.withOpacity(0.1),
                          ),
                          child: TabBar(
                            indicatorSize: TabBarIndicatorSize.tab,
                            dividerColor: Colors.transparent,
                            indicatorColor: Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black,
                            indicator: const BoxDecoration(
                              borderRadius: BorderRadius.all(Radius.circular(10)),
                              color: Colors.white,
                            ),
                            tabs: [
                              Tab(
                                child: Text(
                                  'Collections',
                                  style: TextStyle(
                                    fontWeight: FontWeight.w700,
                                    fontSize: 12.0,
                                    color: Theme.of(context).brightness == Brightness.dark ? Colors.grey : Colors.black,
                                  ),
                                ),
                              ),
                              Tab(
                                child: Text(
                                  'Followers',
                                  style: TextStyle(
                                    fontWeight: FontWeight.w700,
                                    fontSize: 12.0,
                                    color: Theme.of(context).brightness == Brightness.dark ? Colors.grey : Colors.black,
                                  ),
                                ),
                              ),
                              Tab(
                                child: Text(
                                  'Following',
                                  style: TextStyle(
                                    fontWeight: FontWeight.w700,
                                    fontSize: 12.0,
                                    color: Theme.of(context).brightness == Brightness.dark ? Colors.grey : Colors.black,
                                  ),
                                ),
                              ),
                            ],
                          ),
                        ),
                        SizedBox(
                          height: MediaQuery.of(context).size.height * 0.8,
                          child: const TabBarView(
                            children: [
                              CollectionsMyShelf(),
                              FollowersMyShelf(),
                              FollowingMyShelf(),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            );
          } else {
            return const Center(child: Text('No data found'));
          }
        },
      ),
    );
  }
}

import 'package:json_annotation/json_annotation.dart';

part 'user_model.g.dart';

@JsonSerializable(explicitToJson: true)
class UserModel {
  final String status;
  final UserData data;

  UserModel({
    required this.status,
    required this.data,
  });

  factory UserModel.fromJson(Map<String, dynamic> json) => _$UserModelFromJson(json);
  Map<String, dynamic> toJson() => _$UserModelToJson(this);
}

@JsonSerializable(explicitToJson: true)
class UserData {
  final User user;
  final int followersCount;
  final int followingCount;

  UserData({
    required this.user,
    required this.followersCount,
    required this.followingCount,
  });

  factory UserData.fromJson(Map<String, dynamic> json) => _$UserDataFromJson(json);
  Map<String, dynamic> toJson() => _$UserDataToJson(this);
}

@JsonSerializable(explicitToJson: true)
class User {
  @JsonKey(name: '_id')
  final String id;
  final String name;
  final String username;
  final String email;
  final String role;
  final List<String> savedCollection;
  final List<dynamic> cart;
  final List<dynamic> address;
  final int v;
  final String bankName;
  final String accountName;
  final bool activeAffiliate;
  final int redeemable;
  final int redeemed;
  final DateTime updatedAffiliateAt;

  User({
    required this.id,
    required this.name,
    required this.username,
    required this.email,
    required this.role,
    required this.savedCollection,
    required this.cart,
    required this.address,
    required this.v,
    required this.bankName,
    required this.accountName,
    required this.activeAffiliate,
    required this.redeemable,
    required this.redeemed,
    required this.updatedAffiliateAt,
  });

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}



// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'user_model.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

UserModel _$UserModelFromJson(Map<String, dynamic> json) => UserModel(
      status: json['status'] as String,
      data: UserData.fromJson(json['data'] as Map<String, dynamic>),
    );

Map<String, dynamic> _$UserModelToJson(UserModel instance) => <String, dynamic>{
      'status': instance.status,
      'data': instance.data.toJson(),
    };

UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
      user: User.fromJson(json['user'] as Map<String, dynamic>),
      followersCount: (json['followersCount'] as num).toInt(),
      followingCount: (json['followingCount'] as num).toInt(),
    );

Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
      'user': instance.user.toJson(),
      'followersCount': instance.followersCount,
      'followingCount': instance.followingCount,
    };

User _$UserFromJson(Map<String, dynamic> json) => User(
      id: json['_id'] as String,
      name: json['name'] as String,
      username: json['username'] as String,
      email: json['email'] as String,
      role: json['role'] as String,
      savedCollection: (json['savedCollection'] as List<dynamic>)
          .map((e) => e as String)
          .toList(),
      cart: json['cart'] as List<dynamic>,
      address: json['address'] as List<dynamic>,
      v: (json['v'] as num).toInt(),
      bankName: json['bankName'] as String,
      accountName: json['accountName'] as String,
      activeAffiliate: json['activeAffiliate'] as bool,
      redeemable: (json['redeemable'] as num).toInt(),
      redeemed: (json['redeemed'] as num).toInt(),
      updatedAffiliateAt: DateTime.parse(json['updatedAffiliateAt'] as String),
    );

Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
      '_id': instance.id,
      'name': instance.name,
      'username': instance.username,
      'email': instance.email,
      'role': instance.role,
      'savedCollection': instance.savedCollection,
      'cart': instance.cart,
      'address': instance.address,
      'v': instance.v,
      'bankName': instance.bankName,
      'accountName': instance.accountName,
      'activeAffiliate': instance.activeAffiliate,
      'redeemable': instance.redeemable,
      'redeemed': instance.redeemed,
      'updatedAffiliateAt': instance.updatedAffiliateAt.toIso8601String(),
    };

2

Answers


  1. class UserModel {
      final String status;
      final UserData data;
    error from: 
    UserModel({
        required this.status,
        required this.data,
      });
    
      factory UserModel.fromJson(Map<String, dynamic> json) => _$UserModelFromJson(json);
      Map<String, dynamic> toJson() => _$UserModelToJson(this);
    }
    

    here, a null value is coming from API into some field of Map type in this model. just check for nullable model fields

    Login or Signup to reply.
  2. in the user class ensure passing the key coming from API response whith same name for key
    if tou generate class manully try to use some website to generate class in right method like this website then in function fetchUserData befor assigning the data for model try to print it to view ehat the value comes error in response

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search