I`m trying to work with JSON and display data in a widget
I`m getting json from website
https://jsonplaceholder.typicode.com/posts
And I'm trying to display data from json in ListView
I`m click on button, titles are displayed in list
It's working fine
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
class NewsWidget extends StatefulWidget {
const NewsWidget({super.key});
@override
State<NewsWidget> createState() => _NewsWidgetState();
}
class _NewsWidgetState extends State<NewsWidget> {
var jsonNews;
getNewsNYT() async {
var dio = Dio();
final response =
await dio.get('https://jsonplaceholder.typicode.com/posts');
setState(() {
jsonNews = response.data;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('JSON'),
actions: [
ElevatedButton(
onPressed: getNewsNYT,
child: const Text('NYT'),
),
],
),
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
title: Text(jsonNews[index]['title']),
),
);
},
itemCount: jsonNews == null ? 0 : jsonNews.length,
),
);
}
}
After that I tried with a real example and took the New York Times API
There I display popular news from the main one, the request itself looks like this
final response = await dio.get('https://api.nytimes.com/svc/topstories/v2/home.json?api-key=my-key');
I add my key at the end of the request correctly
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
class NewsWidget extends StatefulWidget {
const NewsWidget({super.key});
@override
State<NewsWidget> createState() => _NewsWidgetState();
}
class _NewsWidgetState extends State<NewsWidget> {
var jsonNews;
getNewsNYT() async {
var dio = Dio();
final response = await dio.get(
'https://api.nytimes.com/svc/topstories/v2/home.json?api-key=0SDaGP4DLAzR5OtGxVC6ObfhNljic18h');
setState(() {
jsonNews = response.data;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('JSON'),
actions: [
ElevatedButton(
onPressed: getNewsNYT,
child: const Text('NYT'),
),
],
),
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
title: Text(jsonNews[index]['title']),
),
);
},
itemCount: jsonNews == null ? 0 : jsonNews.length,
),
);
}
}
I get an error there
title: Text(jsonNews[index]['title']),
The method '[]' was called on null.
I open the url to check that there really is data
I use https://jsonformatter.org/ to make it clear
As a result, I see that before Map String information is placed that I do not need. If it is removed, the Map will work correctly.
https://i.stack.imgur.com/eRG7M.jpg
How correctly to work with result of request? For example, I want to display news titles in a ListView.
Solution
getNewsNYT() async {
var dio = Dio();
final response = await dio.get(
'https://api.nytimes.com/svc/topstories/v2/home.json?api-key=0SDaGP4DLAzR5OtGxVC6ObfhNljic18h');
final jsonBody = response.data['results']; // beacause main map in section results:
setState(() {
jsonNews = jsonBody;
});
}
CodePudding user response:
I think The problem is here jsonNews = response.data, the data you need is in the ['results'] section. so try this
getNewsNYT() async {
//var dio = Dio();
final response = await http.get(Uri.parse(
'https://api.nytimes.com/svc/topstories/v2/home.json?api-key=0SDaGP4DLAzR5OtGxVC6ObfhNljic18h'));
setState(() {
var jsonBody = convert.jsonDecode(response.body);
jsonNews = jsonBody['results'];
});
}
then you will get this result results
CodePudding user response:
did you try to use the result key like that:
TextText(jsonNews[index]['results'][index]['title']);
this might not work because you have an inner list on the results key try to extract the result list and use it in listview