0

I'm following flutter's documentation for a api integration but I'm getting this error type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'

The sample response api gives according to its documentation is this Link to api

[
  {
    "category": "technology",
    "datetime": 1596589501,
    "headline": "Square surges after reporting 64% jump in revenue, more customers using Cash App",
    "id": 5085164,
    "image": "https://image.cnbcfm.com/api/v1/image/105569283-1542050972462rts25mct.jpg?v=1542051069",
    "related": "",
    "source": "CNBC",
    "summary": "Shares of Square soared on Tuesday evening after posting better-than-expected quarterly results and strong growth in its consumer payments app.",
    "url": "https://www.cnbc.com/2020/08/04/square-sq-earnings-q2-2020.html"
  },
  {
    "category": "business",
    "datetime": 1596588232,
    "headline": "B&G Foods CEO expects pantry demand to hold up post-pandemic",
    "id": 5085113,
    "image": "https://image.cnbcfm.com/api/v1/image/106629991-1595532157669-gettyimages-1221952946-362857076_1-5.jpeg?v=1595532242",
    "related": "",
    "source": "CNBC",
    "summary": "\"I think post-Covid, people will be working more at home, which means people will be eating more breakfast\" and other meals at home, B&G CEO Ken Romanzi said.",
    "url": "https://www.cnbc.com/2020/08/04/bg-foods-ceo-expects-pantry-demand-to-hold-up-post-pandemic.html"
  },
  {
    "category": "top news",
    "datetime": 1596584406,
    "headline": "Anthony Levandowski gets 18 months in prison for stealing Google self-driving car files",
    "id": 5084850,
    "image": "https://image.cnbcfm.com/api/v1/image/106648265-1596584130509-UBER-LEVANDOWSKI.JPG?v=1596584247",
    "related": "",
    "source": "CNBC",
    "summary": "A U.S. judge on Tuesday sentenced former Google engineer Anthony Levandowski to 18 months in prison for stealing a trade secret from Google related to self-driving cars months before becoming the head of Uber Technologies Inc's rival unit.",
    "url": "https://www.cnbc.com/2020/08/04/anthony-levandowski-gets-18-months-in-prison-for-stealing-google-self-driving-car-files.html"
  }
  }]

This is my code I followed from here

News class:

class News {
  final int id;
  final String category;
  final String datetime;
  final String headline;
  final String image;
  final String source;
  final String related;
  final String summary;
  final String url;

  News(
      {required this.id,
      required this.category,
      required this.datetime,
      required this.headline,
      required this.image,
      required this.source,
      required this.related,
      required this.summary,
      required this.url});

  factory News.fromJson(Map<String, dynamic> json) {
    return News(
      id: json['id'],
      category: json['category'],
      datetime: json['datetime'],
      headline: json['headline'],
      image: json['image'],
      related: json['realted'],
      source: json['source'],
      summary: json['summary'],
      url: json['url'],
    );
  }
}

Data fetching screen:

class MarketingNewsScreen extends StatefulWidget {
  const MarketingNewsScreen({Key? key}) : super(key: key);

  @override
  State<MarketingNewsScreen> createState() => _MarketingNewsScreenState();
}

class _MarketingNewsScreenState extends State<MarketingNewsScreen> {
  late Future<News> futureNews;
  Future<News> fetchNews() async {
    final response = await http.get(Uri.parse(
        'https://finnhub.io/api/v1/news?category=general&token=mytokenhiddenhere'));

    if (response.statusCode == 200) {
      // If the server did return a 200 OK response,
      // then parse the JSON.
      return News.fromJson(jsonDecode(response.body));
    } else {
      // If the server did not return a 200 OK response,
      // then throw an exception.
      throw Exception('Failed to load album');
    }
  }

  @override
  void initState() {
    super.initState();
    futureNews = fetchNews();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          centerTitle: true,
          automaticallyImplyLeading: false,
          leading: IconButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              icon: const Icon(Icons.arrow_back_ios)),
          title: const Text("Marketing News")),
      body: Center(
        child: FutureBuilder<News>(
          future: futureNews,
          builder: (context, abc) {
            if (abc.hasData) {
              return Text(abc.data!.category);
            } else if (abc.hasError) {
              print("${abc.error}");
              return Text("${abc.error}");
            }
            return const CircularProgressIndicator();
          },
        ),
      ),
    );
  }
}

Everything seems fine and well according to the documentation but it's giving the error and not working. I'm new to flutter especially to api side of it so I don't know what's wrong I'm doing here. Any help will be highly appreciated

0

1 Answer 1

2

Your api result is list but in your model class you expect map,change your model class to this:

static List<News> fromJson(List _list) {
    List<News> result = [];

    for (var item in _list) {
      var news = News(
      id: item['id'],
      category: item['category'],
      datetime: item['datetime'],
      headline: item['headline'],
      image: item['image'],
      related: item['realted'],
      source: item['source'],
      summary: item['summary'],
      url: item['url'],
    );
      result.add(news);
    }
    return result;
  }

and also replace FutureBuilder<News> with FutureBuilder<List<News>> and all Future<News> with Future<List<News>>

Sign up to request clarification or add additional context in comments.

2 Comments

I've replaced the code but its giving error on init futureNews = fetchNews(); here. It asks to add cast futureNews = fetchNews() as as Future<News>; and when I add it gives error type 'Future<List<News>>' is not a subtype of type 'Future<News>?' in type cast
I updated my answer. as you can see in sample response, you have list of news so when you pars it you give list of news not single news.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.