Search code examples
flutterapidart

issues with data received from api,data maybe a string or null


i'am using tmdb to fetch movies data,all things work alright till a try to fetch movies from the third page of popular movies, here is the error i got

Exception occured: type 'Null' is not a subtype of type 'String' stackTrace: #0

this is the fetch function witch return the error:

class DioApiClient implements ApiClient {
  final Dio dio = Dio();
  final Api api = Api();

  @override
  Future<List<MovieModel>> getDataFrom(String endPoint,
      {Map<String, dynamic>? params}) async {
    final String url = "${api.baseURL}/$endPoint";
    log("from api client :$url/$params");

    Map<String, dynamic> queryParameters = {
      'api_key': api.apiKey,
      // 'language': 'en-US',
    };
    if (params != null) {
      queryParameters.addAll(params);
    }

    try {
      final response = await dio.get(url, queryParameters: queryParameters);

      log(" status code : ${response.statusCode}");
      if (response.statusCode == 200) {
        final Map<String, dynamic> data = response.data;
        final List<dynamic> results = data['results'];
        final List<MovieModel> movies =
            results.map((dynamic movie) => MovieModel.fromJson(movie)).toList();

        return movies;
      }

      
    } catch (error, stacktrace) {
      log("Exception occured: $error stackTrace: $stacktrace");
      throw Exception('Failed to load data ');
    }
    throw Exception("data not found");
  }
}

and here is the movie model:

import '../../domain/entities/movie_entity.dart';

class MovieModel {
  final int id;
  final String title;
  final String overview;
  final String posterPath;
  final num voteAverage;
  final String backdropPath;
  final String releaseDate;

  MovieModel({
    required this.id,
    required this.title,
    required this.overview,
    required this.posterPath,
    required this.voteAverage,
    required this.backdropPath,
    required this.releaseDate,
  });

  factory MovieModel.fromJson(Map<String, dynamic> json) {
    return MovieModel(
      id: json['id'],
      title: json['title'],
      overview: json['overview'],
      posterPath: json['poster_path'],
      voteAverage: json['vote_average'],
      backdropPath: json['backdrop_path'],
      releaseDate: json['release_date'],
    );
  }

  MovieEntity toEntity() {
    return MovieEntity(
      id: id,
      title: title,
      overview: overview,
      posterPath: posterPath,
      voteAverage: voteAverage,
      backdropPath: backdropPath,
      releaseDate: releaseDate,
    );
  }
}

i tried to make the backdropPath and posterPath nullable but its the i got same behavior API RESPONSE


Solution

  • Your json can have null values (as you have shown in your screen poster_path and backdrop_path).

    This means the posterPath: json['poster_path'] will crash if it is null, because you try to set a null value inside a non-nullable String. You either make your string nullable or you do a safety check. It's a good practice to set default values if your value is null, like this:

    posterPath: json['poster_path'] != null ? json['poster_path'] : "",
    

    or you use the short variation with the ?? operator:

      posterPath: json['poster_path'] ?? "",
    

    Your fromJson can look like this:

    return MovieModel(
          id: json['id'] ?? 0,
          title: json['title'] ?? "",
          overview: json['overview'] ?? "",
          posterPath: json['poster_path'] ?? "",
          voteAverage: json['vote_average'] ?? 0,
          backdropPath: json['backdrop_path'] ?? "",
          releaseDate: json['release_date'] ?? "",
        );