0
votes

I am new to flutter and I tried fetching data from API but I got the error

type'_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Iterable<dynamic>'.

I am fetching news data from the API. I tried this for simple API and it worked and when I tried it for a complex API with some changes in the dart code I got this error.

Sorry if I didn't explain correctly. I have pasted all the code that has been used for this API.

I am not getting any solution. I am posting my code here.

post.dart

 class Post {
     List<Articles> articles;

     Post({this.articles});

     factory Post.fromJson(Map<String, dynamic> json) {
        return Post(
           articles: json['articles'].map((value) => new Articles.fromJson(value)).toList(),
     );
  }
}

article.dart

 class Articles{
     final String title;
     final String description;
     final String url;
     final String urlToImage;
     final String publishedAt;
     final String content;

      Articles({this.title, this.description, this.url, this.urlToImage, this.publishedAt, this.content});

      factory Articles.fromJson(Map<String, dynamic> json) {
          return Articles(
              title: json['title'],
              description: json['description'],
              url: json['url'],
              urlToImage: json['urlToImage'],
              publishedAt: json['publishedAt'],
              content: json['content'],
         );
       }

   }

technology_post.dart

   Future<List<Post>> fetchPost() async {
      final response = await http.get('https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=47ada2986be0434699996aaf4902169b');
      if (response.statusCode == 200) {
          var responseData = json.decode(response.body);
          List<Post> posts = [];
          for(var item in responseData){
             Post news = Post.fromJson(item);
             posts.add(news);
          }
       return posts;
      } else {
           throw Exception('Failed to load post');
      }
  }

  class Technology extends StatelessWidget{
      final Future<List<Post>> post;
      Technology({Key key, this.post}) : super (key : key);

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: FutureBuilder<List<Post>>(
               future: post,
               builder: (context, snapshot) {
                  if (snapshot.hasData) {
                      return ListView.builder(
                         itemBuilder: (BuildContext context, int index){
                         var dataStored = "";
                         for(var i = 0; i < 10; i++){
                             dataStored = snapshot.data.articles[i].title;
                             return ListTile(
                                title: Text(dataStored),
                             );
                         }
                     }
                );
        } else if (snapshot.hasError) {
          return Text("${snapshot.error}");
        }
         return CircularProgressIndicator();
        },
      ),
     ),
   );
  }
}

homescreen.dart

  TabBarView(
              children: [
                Technology(post: fetchPost()),
                Text('General'),
                Text('Cricket')
              ]

I have posted all the required code I hope. If you want to see the API you can see that here

Sorry if I have pasted much code here.

Why am I getting this error and how can I resolve this.

Thanks in advance.

2

2 Answers

1
votes

According to your json, there is no List but only Post as json is json object. So change your fetchPost() function as follows:

    Future<Post> fetchPost() async {
    final response = await http.get(
    'https://newsapi.org/v2/top-headlines? 
    sources=techcrunch&apiKey=$YOUR_API_KEY');
    if (response.statusCode == 200) {
    var responseData = jsonDecode(response.body);
    var post = Post.fromJson(responseData);
    return post;
    } else {
    throw Exception('Failed to load post');
    }
    }

NOTE : Remove your api key from your question and paste json only for privacy.

And change your technology class to

    class Technology extends StatelessWidget {
                      final Future<Post> post;

                      Technology({Key key, this.post}) : super(key: key);

                      @override
                      Widget build(BuildContext context) {
                        return Scaffold(
                          body: Center(
                            child: FutureBuilder<Post>(
                              future: post,
                              builder: (context, snapshot) {
                                if (snapshot.hasData) {
                                  return ListView.builder(
                                      itemBuilder: (BuildContext context, int index) {
                                    return Text(snapshot.data.articles[0].publishedAt);
                                  });
                                } else if (snapshot.hasError) {
                                  return Text("${snapshot.error}");
                                }
                                return CircularProgressIndicator();
                              },
                            ),
                          ),
                        );
                      }
                    }

and your main problem is also that you have not cast json['articles'] to list. you should change Post.fromJson function to

                    factory Post.fromJson(Map<String, dynamic> json) {
              return Post(
                articles: (json['articles'] as List).map((value) => new Articles.fromJson(value)).toList(),
              );
            }

This should solve your problem.

0
votes

You should check correct response type Int with String. I see your API status: "ok" and sure you check correctly.