chumberjosh
chumberjosh

Reputation: 516

Flutter 'Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<class>'

I'm getting data from an API and i'm trying to push that data into two variables. I can access part of the data being returned but not all of it, I can print all of the data but when I try to access a specific part of it, it doesn't work.

E.G: res = response from API

print(res.data); // This works
print(res.feeds); // This doesn't work
print(res.feeds.id); // This doesn't work

The error I am getting is:

'Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<FeedItem>'

This is how i'm converting and reading the data:

class FeedData {
  String data;
  List<FeedItem> feeds;

  FeedData({this.data, this.feeds});

  factory FeedData.fromJson(Map<String, dynamic> json) {
    return FeedData(
      data: json['data'],
      feeds: json['feeds'],
    );
  }
}

I can read and access the 'data' but not the 'feeds' which is my problem, I need to be able to access the data in the 'feeds' The 'FeedItem' class is built in the same way as the 'FeedData' class so I'm sure that it is built properly

This is how I'm calling the data:

getUserFeed() async {
    FeedData res = FeedData.fromJson(
        await requests.get(url: 'feeds/u?u=jxchumber&PageNumber=1'));
    print(res.data);
    // res.data works
    print(res.feeds);
    // res.feeds doesn't work
  }

This is the data being returned from the API:

{
    "data": "default",
    "feeds": [
        {
            "id": 2,
            "photoUrl": "https://cartalkio-image-storage-dev.s3.eu-west-2.amazonaws.com/o85DvOaTXXE.jpg",
            "description": "Magna duis consectetur sit ut commodo non eiusmod.",
            "dateAdded": "0001-01-01T00:00:00",
            "isMain": false,
            "publicId": null,
            "isImage": true,
            "mainImage": "https://randomuser.me/api/portraits/men/76.jpg",
            "userId": 9,
            "likers": null,
            "username": "Larsen",
            "thumbnail": null,
            "likes": 0
        },
        {
            "id": 4,
            "photoUrl": "https://cartalkio-image-storage-dev.s3.eu-west-2.amazonaws.com/lXR833PRh3g.jpg",
            "description": "Magna duis consectetur sit ut commodo non eiusmod.",
            "dateAdded": "0001-01-01T00:00:00",
            "isMain": false,
            "publicId": null,
            "isImage": true,
            "mainImage": "https://randomuser.me/api/portraits/men/4.jpg",
            "userId": 8,
            "likers": null,
            "username": "Lloyd",
            "thumbnail": null,
            "likes": 0
        },
}

Upvotes: 2

Views: 3506

Answers (4)

bluenile
bluenile

Reputation: 6029

The error is because you are not passing json['feeds'] as a List. Your FeedData class will have to be changed to the following, this is assuming that your FeedItem class also has a fromJson method :

class FeedData {
  String data;
  List<FeedItem> feeds;

  FeedData({this.data, this.feeds});

  factory FeedData.fromJson(Map<String, dynamic> json) {
    return FeedData(
      data: json['data'],
      feeds: List.from(json['feeds']).map((item)=>FeedItem.fromJson(item)).toList(),
    );
  }
}

Please see the working code based on your data. You can also load the following code on DartPad https://dartpad.dev/24694a911ddd0619277f5780573086f1

void main() {

  Map<String, dynamic> json = {
    "data": "default",
    "feeds": [
        {
            "id": 2,
            "photoUrl": "https://cartalkio-image-storage-dev.s3.eu-west-2.amazonaws.com/o85DvOaTXXE.jpg",
            "description": "Magna duis consectetur sit ut commodo non eiusmod.",
            "dateAdded": "0001-01-01T00:00:00",
            "isMain": false,
            "publicId": null,
            "isImage": true,
            "mainImage": "https://randomuser.me/api/portraits/men/76.jpg",
            "userId": 9,
            "likers": null,
            "username": "Larsen",
            "thumbnail": null,
            "likes": 0
        },
        {
            "id": 4,
            "photoUrl": "https://cartalkio-image-storage-dev.s3.eu-west-2.amazonaws.com/lXR833PRh3g.jpg",
            "description": "Magna duis consectetur sit ut commodo non eiusmod.",
            "dateAdded": "0001-01-01T00:00:00",
            "isMain": false,
            "publicId": null,
            "isImage": true,
            "mainImage": "https://randomuser.me/api/portraits/men/4.jpg",
            "userId": 8,
            "likers": null,
            "username": "Lloyd",
            "thumbnail": null,
            "likes": 0
        },
      ]
};
  
  
  FeedData feedData = FeedData.fromJson(json);
  print(feedData.feeds.length);
}


class FeedData {
  String data;
  List<FeedItem> feeds;

  FeedData({this.data, this.feeds});

  factory FeedData.fromJson(Map<String, dynamic> json) {
    return FeedData(
      data: json['data'],
      feeds: List.from(json['feeds']).map((item)=>FeedItem.fromJson(item)).toList(),
    );
  }
}


class FeedItem {
  int id;
  String photoUrl;
  String description;
  String dateAdded;
  bool isMain;
  Null publicId;
  bool isImage;
  String mainImage;
  int userId;
  Null likers;
  String username;
  Null thumbnail;
  int likes;

  FeedItem(
      {this.id,
      this.photoUrl,
      this.description,
      this.dateAdded,
      this.isMain,
      this.publicId,
      this.isImage,
      this.mainImage,
      this.userId,
      this.likers,
      this.username,
      this.thumbnail,
      this.likes});

  FeedItem.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    photoUrl = json['photoUrl'];
    description = json['description'];
    dateAdded = json['dateAdded'];
    isMain = json['isMain'];
    publicId = json['publicId'];
    isImage = json['isImage'];
    mainImage = json['mainImage'];
    userId = json['userId'];
    likers = json['likers'];
    username = json['username'];
    thumbnail = json['thumbnail'];
    likes = json['likes'];
  }
}

Upvotes: 3

Hitesh Garg
Hitesh Garg

Reputation: 250

When you are doing feeds: json['feeds'], You are basically trying to assign a Map<String,dynamic> to a class FeedItem , Moreover you want to assign a complete list as List<Map<String,dynamic>> to List<FeedItem , The problem is that flutter just can't parse the data automatically and assign like this , You need to go deep level by level and assign Map<String,dynamic> to FeedItem and then finally convert it to a List

I will share a piece of code based on my knowledge, how I tackle this type of problem and I believe that will give you better insight about your problem ( if not solve it )

Future<void> getData() async {
http.Response response =
    await http.get('Example address');
if (response.statusCode == HttpStatus.ok) {
//if the status code is 200 or 'OK' parse the data and convert Outer layer as List
//after that , Map each element as a FeedItem and finally convert the result to List
  feeds = (json.decode(response.body) as List)
      .map<FeedItem>(
          (_feed) => FeedItem.fromJSON(_feed))
      .toList();
} else {
  throw response;
}

}

Upvotes: 3

Adelina
Adelina

Reputation: 11881

You are not converting feedItems to objects

  factory FeedData.fromJson(Map<String, dynamic> json) {
    return FeedData(
      data: json['data'],
      feeds: json['feeds'],  # <- here is the problem
    );

Should be something like this:

feeds: (json['feeds'] as List)
        ?.map((e) =>
            e == null ? null : FeedItem.fromJson(e as Map<String, dynamic>))
        ?.toList(),

Upvotes: 1

Muhammad Tameem Rafay
Muhammad Tameem Rafay

Reputation: 4575

Please change this code

print(res.feeds);    -->  print(res.feeds[0]);
print(res.feeds.id); --> print(res.feeds[0].id);

Upvotes: 0

Related Questions