Unable to display the parsed JSON in Future Builder in flutter - json

I was trying to fetch data results from a REST API and then display it in the UI.
So everything went well the JSON was parsed well the try and catch method was working fine.
But somehow the code was not able to display the parsed results in the UI.
Neither it gave me an error or exception.
I have been struggling to attain the desired result for quite the past few days.
This is how the JSON looks like:
{
"data-description": "This api will return an array of objects to be placed in the order status timeline on the second screen",
"order-status": "Success",
"status-objects": [
{
"type": "Payment",
"status": "completed",
"date": "2021-07-02T00:00:00",
"time": "12:00AM"
},
{
"type": "Units Allocated",
"status": "by Axis",
"date": "2021-07-13T00:00:00",
"time": "12:00AM"
}
]
}
What type of UI I want to achieve after doing this.
In order to make the problem more clearly, I will be attaching my code snippets.
Model Class
Transaction transactionFromJson(String str) =>
Transaction.fromJson(json.decode(str));
String transactionToJson(Transaction data) => json.encode(data.toJson());
class Transaction {
Transaction({
required this.dataDescription,
required this.orderStatus,
required this.statusObjects,
});
String dataDescription;
String orderStatus;
List<StatusObject> statusObjects;
factory Transaction.fromJson(Map<String, dynamic> json) => Transaction(
dataDescription: json["data-description"],
orderStatus: json["order-status"],
statusObjects: List<StatusObject>.from(
json["status-objects"].map((x) => StatusObject.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"data-description": dataDescription,
"order-status": orderStatus,
"status-objects":
List<dynamic>.from(statusObjects.map((x) => x.toJson())),
};
}
class StatusObject {
StatusObject({
required this.type,
required this.status,
required this.date,
required this.time,
});
String type;
String status;
DateTime date;
String time;
factory StatusObject.fromJson(Map<String, dynamic> json) => StatusObject(
type: json["type"],
status: json["status"],
date: DateTime.parse(json["date"]),
time: json["time"],
);
Map<String, dynamic> toJson() => {
"type": type,
"status": status,
"date": date.toIso8601String(),
"time": time,
};
}
API_Manager where the parsing and fetching took place
Service Class
class API_Manager {
static Future<Transaction> getDetails() async {
var client = http.Client();
var transactions;
try {
var response = await client.get(
Uri.https("https://hereistheurl", "/accounts/test-data/"));
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = jsonDecode(jsonString);
transactions = Transaction.fromJson(jsonMap);
}
} catch (e) {
return transactions;
}
return transactions;
}
}
The UI component where I wanted to display the parsed JSON:
Code
FutureBuilder<Transaction>(
future: API_Manager.getDetails(),
builder: (context, snapshot) {
if (snapshot.hasData) {
var data = snapshot.data!.statusObjects;
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) =>
Text('$index : ${data[index].status}'),
);
}
return Text('Something was wrong!');
},
),
I am quite sure that I have been missing a very small piece of code to make it work.
I have been working on this piece of code for quite a few days but am unable to do it.
I request you, people, to please help me out in attaining the result or point out the piece of code that I have left out.
Will appreciate it if you could help me in any possible way.

Bro, your are using wrongly *builder widgets, I've made some corrections at your code:
Service class
typedef JMap = Map<String, dynamic>;
class API_Manager {
static Future<Transaction> getData() {
return Future.delayed(Duration(seconds: 1), () => raw_response)
.then((response) {
return Transaction.fromJson(jsonDecode(response) as JMap);
});
}
}
const raw_response = '''
{
"data-description": "This api will return an array of objects to be placed in the order status timeline on the second screen",
"order-status": "Success",
"status-objects": [
...
]
}
''';
Presentation
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hi!'),
centerTitle: true,
),
body: Container(
child: FutureBuilder<Transaction>(
future: API_Manager.getData(),
builder: (context, snapshot) {
if (snapshot.hasError)
return Text(snapshot.error.toString());
if (snapshot.connectionState == ConnectionState.waiting)
return Center(child: CircularProgressIndicator());
if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
final data = snapshot.data!.statusObjects;
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) => Text('$index : ${data[index].status}'),
);
}
return Text('Something was wrong!');
},
),
),
);
}
}
Result:
UPDATED(1)
static Future<Transaction?> getDetails(String url) {
return http.get(Uri.parse(url))
.then((response) {
if (response.statusCode == 200)
return Transaction.fromJson(jsonDecode(response.body) as JMap);
return null;
})
.catchError((err) { print(err); });
}

Related

Flutter - How to parse JSON data?

I want to parse my JSON data and display all the nodeValues of the rows and not just [7] (which contains the word hello), however my FutureBuilder doesn't display the JSON data (stuck on CircularProgressIndicator) even though i'm following the correct JSON path.
//Updated code
class Feed {
String title;
Feed({this.title});
factory Feed.fromJson(Map<String, dynamic> json) {
return Feed(
title: json["data"]["tables"][0]["rows"][7]["cols"][1]["nodeValue"]);
}
}
//I am making a post method to an API that returns me a JSON output.
Future<List<Feed>> post() async {
final Response<String> result =
await Dio().get('https://example.com');
String _baseUrl = "https://html2json.com/api/v1";
var options = Options(
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
followRedirects: false,
);
final response = json.decode(result.data);
final responseJson = await Dio().post(
_baseUrl,
data: response,
options: options,
);
if (responseJson.statusCode == 200) {
return (response as List).map((json) => Feed.fromJson(json)).toList();
} else {
return null;
}
}
//This is stuck on CircularProgressIndicator();
FutureBuilder(
future: post(),
builder: (context, AsyncSnapshot<List<Feed>> snap) {
if (snap.hasData) {
return ListView.builder(
itemCount: snap.data.length,
itemBuilder: (BuildContext context, int index) {
return Text(snap.data[index].title);
});
} else {
return CircularProgressIndicator();
}
});
I changed a few things to make your code work with the json place holder. You were using response.statusCode == 200, but response has no status code, the status code is on the var link.
class Feed {
String title;
Feed({this.title});
factory Feed.fromJson(Map<String, dynamic> json) {
return Feed(title: json["title"]);
}
}
Future<List> post() async {
final Response<String> result = await Dio().get('https://jsonplaceholder.typicode.com/todos');
final response = json.decode(result.data);
if (result.statusCode == 200) {
return (response as List)
.map((json) => Feed.fromJson(json))
.toList();
} else {
return null;
}
}
return FutureBuilder(
future: post(),
builder: (context, AsyncSnapshot<List> snap) {
if (snap.hasData) {
return ListView.builder(
itemCount: snap.data.length,
itemBuilder: (BuildContext context, int index) {
return Text(snap.data[index].title);
});
} else {
return CircularProgressIndicator();
}
});

Why am I getting Unhandled Exception: DatabaseException(datatype mismatch) though everything seems perfect?

I am using an API,to fetch data and display it in a list view after some constraints.I am fetching the data from the API ,it is printing as well and getting stored as well.But still I am getting Unhandled Exception: DatabaseException(datatype mismatch),though I checked the order in which I have put them down in correct.I am really fed up with this JSON parsing.It is a real pain actually speaking.
Below is the list of dart files I have used in my flutter project:
This is my main file,where I will be displaying the data in a list view:
import 'package:flutter/material.dart';
import 'services.dart';
import 'db_provider.dart';
void main() => runApp(Main());
class Main extends StatefulWidget {
#override
_MainState createState() => _MainState();
}
class _MainState extends State<Main> {
var isLoading = false;
_loadFromApi() async {
setState(() {
isLoading = true;
});
var apiProvider = Services();
await apiProvider.getAllCustomers();
// wait for 2 seconds to simulate loading of data
await Future.delayed(const Duration(seconds: 2));
setState(() {
isLoading = false;
});
}
Widget _buildEmployeeListView() {
return FutureBuilder(
future: DBProvider.db.getAllCustomers(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return ListView.separated(
separatorBuilder: (context, index) =>
Divider(
color: Colors.black12,
),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: Text(
"${index + 1}",
style: TextStyle(fontSize: 20.0),
),
title: Text(
"Name: ${snapshot.data[index].name} "),
subtitle: Text('status: ${snapshot.data[index].status}'),
);
},
);
}
},
);
}
#override
void initState() {
super.initState();
_loadFromApi();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Customer details'),
),
body: _buildEmployeeListView(),
),
);
}
}
Below is my JSON data:
{
"list":[
{
"id":"MnJJA0dbuw",
"name":"Anand Sharma",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Anand.jpeg",
"gender":"m",
"age":46,
"date":"23/11/2019",
"status":"onboarded"
},
{
"id":"MnZmmmbuw",
"name":"Malashri Lal",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Vishesh.jpg",
"gender":"f",
"age":70,
"date":"01/10/2019",
"status":"active"
},
{
"id":"MnZy10dpsq",
"name":"Suhasini Haidar",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Suhasini.jpg",
"gender":"f",
"age":30,
"date":"23/03/2019",
"status":"left"
},
{
"id":"HOnmFt5jA",
"name":"Vishesh Mahajan",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Vishesh.jpg",
"gender":"m",
"age":34,
"date":"05/05/2019",
"status":"active"
},
{
"id":"MnZy10dxyz",
"name":"Anand Neelakantan",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Anand.jpeg",
"gender":"m",
"age":46,
"date":"03/10/2019",
"status":"left"
},
{
"id":"MnZy1JJbuw",
"name":"Malashri",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Malashri.jpg",
"gender":"f",
"age":65,
"date":"04/01/2019",
"status":"active"
},
{
"id":"JKAS10dbuw",
"name":"Meenakshi Madhavan",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Meenakshi.jpg",
"gender":"f",
"age":35,
"date":"01/03/2020",
"status":"left"
},
{
"id":"sOw8c6BOug",
"name":"Fintan",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Fintan.jpg",
"gender":"m",
"age":55,
"date":"09/12/2019",
"status":"onboarded"
},
{
"id":"MnZy10dlll",
"name":"Jaishree Periwal",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Jaishree.jpg",
"gender":"f",
"age":50,
"date":"01/02/2020",
"status":"active"
},
{
"id":"KbN3VELflA",
"name":"Anukriti Upadhyay",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Anukriti.jpg",
"gender":"f",
"age":30,
"date":"31/01/2020",
"status":"onboarded"
}
]
}
Below is the PODO file I have created:
// To parse this JSON data, do
//
// final customerInfo = customerInfoFromJson(jsonString);
import 'dart:convert';
CustomerInfo customerInfoFromJson(String str) => CustomerInfo.fromJson(json.decode(str));
String customerInfoToJson(CustomerInfo data) => json.encode(data.toJson());
class CustomerInfo {
CustomerInfo({
this.list,
});
List<ListElement> list;
factory CustomerInfo.fromJson(Map<String, dynamic> json) => CustomerInfo(
list: List<ListElement>.from(json["list"].map((x) => ListElement.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"list": List<dynamic>.from(list.map((x) => x.toJson())),
};
}
class ListElement {
ListElement({
this.id,
this.name,
this.img,
this.gender,
this.age,
this.date,
this.status,
});
String id;
String name;
String img;
Gender gender;
int age;
String date;
Status status;
factory ListElement.fromJson(Map<String, dynamic> json) => ListElement(
id: json["id"],
name: json["name"],
img: json["img"],
gender: genderValues.map[json["gender"]],
age: json["age"],
date: json["date"],
status: statusValues.map[json["status"]],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"img": img,
"gender": genderValues.reverse[gender],
"age": age,
"date": date,
"status": statusValues.reverse[status],
};
}
enum Gender { M, F }
final genderValues = EnumValues({
"f": Gender.F,
"m": Gender.M
});
enum Status { ONBOARDED, ACTIVE, LEFT }
final statusValues = EnumValues({
"active": Status.ACTIVE,
"left": Status.LEFT,
"onboarded": Status.ONBOARDED
});
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}
Below is the db provider I have created to store the data.I need to still write the SQL command to properly get the data in the required sorting order.For the time being it is Select *
import 'dart:io';
import 'podo_file.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
//9-22 creating a Database object and instantiating it if not initialized.
class DBProvider {
static Database _database;
static final DBProvider db = DBProvider._();
DBProvider._();
Future<Database> get database async {
// If database exists, return database
if (_database != null) return _database;
// If database don't exists, create one
_database = await initDB();
return _database;
}
initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, 'Customer_Info.db');
return await openDatabase(path, version: 1, onOpen: (db) {},
onCreate: (Database db, int version) async {
await db.execute('CREATE TABLE CUSTOMER_DATA('
'id TEXT PRIMARY KEY,'
'name TEXT,'
'img TEXT,'
'gender TEXT'
'age INTEGER,'
'date TEXT,'
'status TEXT,'
')');
});
}
// Insert employee on database
createCustomer(ListElement newCustomer) async {
await deleteAllCustomers();
final db = await database;
final res = await db.insert('CUSTOMER_DATA', newCustomer.toJson());
return res;
}
// Delete all employees
Future<int> deleteAllCustomers() async {
final db = await database;
final res = await db.rawDelete('DELETE FROM CUSTOMER_DATA');
return res;
}
Future<List<ListElement>> getAllCustomers() async {
final db = await database;
final res = await db.rawQuery("SELECT * FROM CUSTOMER_DATA");
List<ListElement> list =
res.isNotEmpty ? res.map((c) => CustomerInfo.fromJson(c)).toList() : [];
return list;
}
}
Below is the service file I have created which will get the data:
import 'dart:convert';
import 'package:flutter/animation.dart';
import 'package:flutterappincablet/podo_file.dart';
import 'package:http/http.dart' as http;
import 'db_provider.dart';
class Services {
Future<List<ListElement>> getAllCustomers() async {
var url = "https://5w05g4ddb1.execute-api.ap-south-1.amazonaws.com/dev/profile/listAll";
final response = await http.get(url);
Map<String, dynamic> map = json.decode(response.body);
print('nnnnnnnnnn');
print(map);
List<dynamic> data = map["list"];
print('xxxxxxxxxxxxxxxxx');
print(data);
return (data as List).map((c) {
print('Inserting $c');
DBProvider.db.createCustomer(ListElement.fromJson(c));
}).toList();
}
}
Below is the screenshot of the error:

displaying selected data on Dropdownbutton on flutter

its actually continuation of my previous question, here i've been successfully populate my list with Json which i retrieved from Get method. as the suggestion, i used futurebuilder widget to build my Dropdownbutton. but my problem is: it cant display any after i picked up the dropdownlist. it crashes.
and i had other thing concerned me. my project is to receive scanned nearby wifi by an esp8266 through http GET method (and later send the password through the apps using POST method). my question is:
when im using this Futurebuilder widget, in which "time" that this app actually made http request? does it refresh all the time?
can i just populate the dropdownmenuitem in just one occasion (perhaps in initstate), then asking for refresh only when i needed it (i.e using a button). i've been trying to do this but it kept failing.
here's my code
Future<List<Post>> getAllPosts(String url) async {
final response = await http.get(url);
return allPostsFromJson(response.body);
}
List<Post> allPostsFromJson(String str) {
final jsonData = json.decode(str);
return new List<Post>.from(jsonData.map((x) => Post.fromJson(x)));
}
class Post {
String name;
String perc;
String pass;
Post({
this.name,
this.perc,
this.pass,
});
factory Post.fromJson(Map<String, dynamic> json) => new Post(
name: json["SSID"],
perc: json["RSSI"],
pass: json["PASS"],
);
Map<String, dynamic> toJson() => {
"SSID": name,
"RSSI": perc,
"PASS": pass,
};
}
class LoginPhaseState extends State<LoginPhase>{
Post selected;
final String uri = 'http://10.0.2.2/data/connection.json';
#override
Widget build(BuildContext context) {
return FutureBuilder<List<Post>>(
future: getAllPosts(uri),
builder: (BuildContext context,
AsyncSnapshot<List<Post>> snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return DropdownButton<Post>(
items: snapshot.data
.map((ssid) => DropdownMenuItem<Post>(
child: Text(ssid.name),
value: ssid,
))
.toList(),
onChanged: (Post value) {
setState(() {
selected = value;
});
},
isExpanded: false,
// value: selected,
hint: Text('Select User'),
);
});
}
}
try this,
Future<List<Post>> getAllPosts(String url) async {
final response = await http.get(url);
return allPostsFromJson(response.body);
}
List<Post> allPostsFromJson(String str) {
final jsonData = json.decode(str);
return new List<Post>.from(jsonData.map((x) => Post.fromJson(x)));
}
class Post {
String name;
String perc;
String pass;
Post({
this.name,
this.perc,
this.pass,
});
factory Post.fromJson(Map<String, dynamic> json) => new Post(
name: json["SSID"],
perc: json["RSSI"],
pass: json["PASS"],
);
Map<String, dynamic> toJson() => {
"SSID": name,
"RSSI": perc,
"PASS": pass,
};
}
class LoginPhaseState extends State<LoginPhase>{
Post selected;
final String uri = 'http://10.0.2.2/data/connection.json';
String _selectedChild= "";
#override
Widget build(BuildContext context) {
return FutureBuilder<List<Post>>(
future: getAllPosts(uri),
builder: (BuildContext context,
AsyncSnapshot<List<Post>> snapshot) {
if (!snapshot.hasData)
return CircularProgressIndicator();
return DropdownButton<Post>(
value: _selectedChild == "" ? null : _selectedChild,
items: snapshot.data
.map((ssid) => DropdownMenuItem<Post>(
child: Text(ssid.name),
value: ssid,
))
.toList(),
onChanged: (Post value) {
setState(() {
_selectedChild = value.name;
selected = value;
});
},
isExpanded: false,
// value: selected,
hint: Text('Select User'),
);
});
}
}

Flutter how to get the data of a json

Good I have the following problem I have a json the following http:// and I have the class to get the data for which use https://app.quicktype.io/ and the code is as follows
// To parse this JSON data, do
//
// final moviesFirstLoad = moviesFirstLoadFromJson(jsonString);
import 'dart:convert';
MoviesFirstLoad moviesFirstLoadFromJson(String str) {
final jsonData = json.decode(str);
return MoviesFirstLoad.fromJson(jsonData);
}
String moviesFirstLoadToJson(MoviesFirstLoad data) {
final dyn = data.toJson();
return json.encode(dyn);
}
class MoviesFirstLoad {
List<Movierecent> movierecent;
MoviesFirstLoad({
this.movierecent,
});
factory MoviesFirstLoad.fromJson(Map<String, dynamic> json) => new MoviesFirstLoad(
movierecent: new List<Movierecent>.from(json["movierecent"].map((x) => Movierecent.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"movierecent": new List<dynamic>.from(movierecent.map((x) => x.toJson())),
};
}
class Movierecent {
int id;
String movieId;
String title;
String genre;
String myear;
String released;
String runtime;
String rated;
String director;
String actors;
String plot;
String imdbrating;
String type;
String production;
int internalid;
String poster;
Movierecent({
this.id,
this.movieId,
this.title,
this.genre,
this.myear,
this.released,
this.runtime,
this.rated,
this.director,
this.actors,
this.plot,
this.imdbrating,
this.type,
this.production,
this.internalid,
this.poster,
});
factory Movierecent.fromJson(Map<String, dynamic> json) => new Movierecent(
id: json["id"],
movieId: json["movieID"],
title: json["title"],
genre: json["genre"],
myear: json["myear"],
released: json["released"],
runtime: json["runtime"],
rated: json["rated"],
director: json["director"],
actors: json["actors"],
plot: json["plot"],
imdbrating: json["imdbrating"],
type: json["type"],
production: json["production"],
internalid: json["internalid"],
poster: json["poster"],
);
Map<String, dynamic> toJson() => {
"id": id,
"movieID": movieId,
"title": title,
"genre": genre,
"myear": myear,
"released": released,
"runtime": runtime,
"rated": rated,
"director": director,
"actors": actors,
"plot": plot,
"imdbrating": imdbrating,
"type": type,
"production": production,
"internalid": internalid,
"poster": poster,
};
}
Now the first label shows me that I should use
final moviesFirstLoad = moviesFirstLoadFromJson(jsonString);
therefore I have the following and here I do not know what to do as accessing the data to place them in a list would be something like
Future<List<Movierecent>> loadMovies() async {
final response = await http.get("http://emovies.evolucionone.com/");
if (response.statusCode == 200){
final moviesFirstLoad = moviesFirstLoadFromJson(response.body);
return moviesFirstLoad.movierecent;
}else{
throw Exception ('Failed to load Data');
}
}
I need help to get the data of the json if someone helps me I have already read several topics but none of them works for me ...
Well I answer my questions myself
This to get the data from json
Future<MoviesFirstLoad> loadMovies() async {
final Response response = await http.get(dogApiUrl);
//final List<Movierecent> posterimage = List<Movierecent>();
if (response.statusCode == 200){
//final responsejson = json.decode(response.body);
final moviesFirstLoad = moviesFirstLoadFromJson(response.body);
// moviesFirstLoad.movierecent.forEach((poster) => posterimage.add(poster));
print(moviesFirstLoad);
return moviesFirstLoad;
}else{
throw Exception ('Failed to load Data');
}
}
to show the data in a list
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Movies')),
body: FutureBuilder(
future: loadMovies(),
builder: (BuildContext context, AsyncSnapshot<AppData> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data.movierecent.length,
itemBuilder: (BuildContext context, int index) {
final Movierecent movie = snapshot.data.movierecent[index];
return ListTile(
title: Text(movie.title),
subtitle: Text(movie.genre),
);
},
);
},
),
);
}
}
loadMovies() returns Future<List<Movierecent>> which is a future. If you want underlying list of movies, you could do someting like
loadMovies().then((List<Movierecent> movieList) {
/* do what you want to do here like invoking setState()....*/
}.catchError((e) {
/* Handle Error scenario here */
};
You might want to refer Dart documentation of Futures

Getting error type'_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Iterable<dynamic>' while fetching data from API in flutter

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.
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.
You should check correct response type Int with String. I see your API status: "ok" and sure you check correctly.