How to parse json in flutter?

2020-05-09 00:40发布

问题:

I want to create a news app and I've used newsapi.org as a source.

I am trying to fetch the JSON data coming by the Http library.

I've provided the entire code below.

It doesn't give me any error but no data loaded and when I print the data it prints everything okay but I can't display it.

I don't what is the problem but all my project has stopped on this problem.

I am looking for a solution for this code because it doesn't work.

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:newly/services/networking.dart';
import 'package:newly/widgets/article.dart';

class NewsScreen extends StatefulWidget {
  @override
  _NewsScreenState createState() => _NewsScreenState();
}

class _NewsScreenState extends State<NewsScreen> {

  List<Article> articles = [];

  NetworkHelper networkHelper = NetworkHelper(
    url:
        'https://newsapi.org/v2/everything?q=bitcoin&apiKey=392495172bab4b3885ae93760df54b91',
  );

  Future<List<Widget>> getNews() async {
    var newsData = await networkHelper.getData();

    for (int i = 0; i < await newsData['articles'].length; i++) {
      var title = await newsData['articles'][i]['title'];
      var urlToImage = await newsData['articles'][i]['urlToImage'];
      var content = await newsData['articles'][i]['content'];
      var author = await newsData['articles'][i]['author'];
      var url = await newsData['articles'][i]['url'];

      print(title);
      print(urlToImage);
      print(url);
      print(content);
      print(author);
      print('123456789123456789123456789123456789');

      articles.add(
        Article(
          author: author,
          content: content,
          title: title,
          url: url,
          urlToImage: urlToImage,
        ),
      );

      print(articles[0].author);

    }

    return articles;
  }

  Future<List<Article>> showArticles() async {
    var data = await get(
      'https://newsapi.org/v2/everything?q=bitcoin&apiKey=392495172bab4b3885ae93760df54b91',
    );

    var dataDecoded = await json.decode(data.body);

    List<Article> articles = [];

    await dataDecoded.forEach(
      (article) {
        articles.add(
          Article(
            author: article['author'],
            content: article['content'],
            title: article['title'],
            url: article['url'],
            urlToImage: article['urlToImage'],
          ),
        );
      },
    );

    return articles;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black,
        centerTitle: true,
        title: Text(
          'Newly',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: FutureBuilder(
        future: getNews(),
        builder: (context, snapshot) {
          return ListView(
            children: articles,
          );
        },
      ),

    );
  }
}

Network Helper :

import 'package:http/http.dart' as http;
import 'dart:convert';

class NetworkHelper {
  NetworkHelper({this.url});

  final String url;

  Future getData() async {
    http.Response response = await http.get(url);

    if (response.statusCode == 200) {
      String data = response.body;

      return json.decode(data);
    } else {
      print('something wrong');
      print(response.statusCode);
    }
  }
}

回答1:

The problem is in showing the articles. and yaa also as @ISpam Ossama says, you have to use setState for adding the data to list like this.

void getNews() async {
var newsData = await networkHelper.getData();

for (int i = 0; i < newsData['articles'].length; i++) {
  var title = newsData['articles'][i]['title'];
  var urlToImage = newsData['articles'][i]['urlToImage'];
  var content = newsData['articles'][i]['content'];
  var author = newsData['articles'][i]['author'];
  var url = newsData['articles'][i]['url'];

  print(title);
  print(urlToImage);
  print(url);
  print(content);
  print(author);
  print('123456789123456789123456789123456789');
  setState(() {
   articles.add(
    Article(
      author: author,
      content: content,
      title: title,
      url: url,
      urlToImage: urlToImage,
    ),
  );
  });
  print(articles[0].author);
}
}

Now, you have to display the articles like this.

ListView.builder(
          itemCount: articles.length,
          itemBuilder: (BuildContext ctxt, int index) {
            return Text(articles[index].title);
          },
        )

Hope it will help you!



回答2:

Try to setState before adding the articles to the array



回答3:

You can also do it using FutureBuilder , If you want otherwise as @Mustafa answer will work.

Future<List<Article>> showArticles() async {
var data = await networkHelper.getData();

List<Article> articlesArr = [];

await data['articles'].forEach(
  (article) {
    articlesArr.add(
      Article(
        author: article['author'],
        content: article['content'],
        title: article['title'],
        url: article['url'],
        urlToImage: article['urlToImage'],
      ),
    );
  },
);
return articlesArr;
}

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black,
        centerTitle: true,
        title: Text(
          'Newly',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: FutureBuilder<List<Article>>(
        future: showArticles(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView(
              children: snapshot.data.map((article) {
                return Container(
                  padding: EdgeInsets.all(8.0),
                  child: Text(article.author),
                );
              }).toList(),
            );
          } else {
            return Container(
              color: Colors.blue,
            );
          }
        },
      ),
    );
  }
}


回答4:

While working with json data

The good practice is to create a model for that and then just fetch the data through the api

creating a model and a class is easy enough and doesn't take effort and makes your work easy ;)

For creating a model for your project

VISIT https://javiercbk.github.io/json_to_dart/

refer the image below

just copy your json data and paste in the textField and you will get your Model Class ready with just one click

for accessing the data

Test _test = Test.fromJson(response.body);

that's it.