Magesh Pandian
Magesh Pandian

Reputation: 9379

Type 'List<dynamic>' is not a subtype of type 'List<int>' where

I am new to Flutter, I try to run one GitHub project but got an error like:

type List dynamic is not a subtype of type List int where.

Github Link

Error Line

List<int> genreIds;

MediaItem._internalFromJson(Map jsonMap, {MediaType type: MediaType.movie})
      :
        type = type,
        id = jsonMap["id"].toInt(),
        voteAverage = jsonMap["vote_average"].toDouble(),
        title = jsonMap[(type == MediaType.movie ? "title" : "name")],
        posterPath = jsonMap["poster_path"] ?? "",
        backdropPath = jsonMap["backdrop_path"] ?? "",
        overview = jsonMap["overview"],
        releaseDate = jsonMap[(type == MediaType.movie
            ? "release_date"
            : "first_air_date")],

        genreIds = jsonMap["genre_ids"];//in this line

}

Above code File

Upvotes: 97

Views: 100749

Answers (8)

krishnaacharyaa
krishnaacharyaa

Reputation: 24990

Given all the solutions. I would like to add many other different ways of achieving the same

  1. List<int> genreIds = List<int>.from(source);
  2. List<int> ints = List.castFrom<dynamic, int>(source);
  3. List<int> ints = source.cast<int>();
  4. List<int> ints = source.map((e) => e as int).toList();

For this use case you can write:

List<int> genreIds = List<int>.from(jsonMap["genre_ids"]);

Hope it helps! :)

Upvotes: 9

Daniel Gomez Rico
Daniel Gomez Rico

Reputation: 15936

If you know how your data is, you could just check the first item type to know if the list is filled with strings or other like:

if (errors is List && errors.isNotEmpty && errors.first is String) {
    return List<String>.from(errors);
}

Upvotes: 0

nguy&#234;n
nguy&#234;n

Reputation: 5326

If you still unsuccess like me, try:

List<int> genreIds = List<int>.from(json.decode(jsonMap["genre_ids"]));

Upvotes: 1

Nathan Agersea
Nathan Agersea

Reputation: 536

I hit this problem because I used generics in my api lib. Here's how I worked around it:

// I've simplified the get for clarity.  My production lib wraps http so I can set / handle base url, headers, time out, and throw when error codes are returned.

Future<T> get<T>(String resource) async {
  var c = Completer<T>();
  try {
    var uri = Uri.parse('$baseUrl/$resource');
    var response = await http.get(uri);
    T result = json.decode(response.body);
    c.complete(result);
  } catch (e) {
    c.completeError(e);
  }
  return c.future;
}

// Service from my feature lib
Future<Iterable<MyDTO>> fetch() async {
  var c = Completer<Iterable<MyDTO>>();
  try {
    List<MyDTO> result = [];        
    // Use Iterable<dynamic> since we cannot use generics to cast when decoding the response body
    var body = await api.get<Iterable<dynamic>>('my-resource');
    
    // cast to List<Map<String, dynamic>
    var myDTOMaps = List<Map<String, dynamic>>.from(body);

    for (var e in myDTOMaps) {
      MyDTO dto = MyDTO.fromMap(e);
      result.add(dto);
    }
    c.complete(result);
  } catch (e) {
    c.completeError(e);
  }
  return c.future;
}

Upvotes: 0

George
George

Reputation: 357

I got a similar error using json setting properties. I fixed it with this:

jsonMap["propId"][0] as int

They are single properties, so the 0 is always correct.

Upvotes: -2

Edi
Edi

Reputation: 2301

A more elegant way could also be initialising new List instead of casting.

var genreIdsFromJson = jsonMap['genre_ids'];
List<int> genreIdsList = new List<int>.from(genreIdsFromJson);

// then you can use gendreIdsList to the mapping function
// ...

gendreIds = genreIdsList
...

Update: As per the documentation

`` All the elements should be instances of E. The elements iterable itself may have any element type, so this constructor can be used to down-cast a List, for example as:

List<SuperType> superList = ...;
List<SubType> subList =
    new List<SubType>.from(superList.whereType<SubType>());

This constructor creates a growable list when growable is true; otherwise, it returns a fixed-length list. ``

Update: Why is it better to initialize than to cast? (Pros / Cons)

Explicit Conversions (Casting): The process is usually associated with information loss or failure to convert between types

Creating new immutable elements is better than casting. Revealing type-related bugs at compile time, more readable code, more maintainable code, better ahead of time (AOT) compilation.

i.e. it is better to try parse or parse a value with predefined method because if the type does not match the value will be null. On the other hand explicitly casting an object or value can throw errors at runtime.

Upvotes: 60

thien nguyen
thien nguyen

Reputation: 326

A shorter way to handle is

genreIds = (jsonMap["genre_ids"] as List)?.map((e) => e as int)?.toList();

Upvotes: 9

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657536

Change

genreIds = jsonMap["genre_ids"];

to

genreIds = jsonMap["genre_ids"].cast<int>();

types in JSON maps or lists don't have concrete generic types. genreIds requires a List<int> not a List (or List<dynamic>), therefore you need to bring the value to its required type before you can assign it.

If you haven't seen this error earlier for the same code, then it's probably because you upgraded to a Dart version where --preview-dart-2 became the default (it was opt-in previously)

Upvotes: 169

Related Questions