Sort JSON in alphabetical order - Flutter - json

I'd like to be able to return my profileList to my ListView in alphabetical order.
I have my "All people" class which has a ListView widget using the json and creating a list of people.
The code below is from my All People class where I'm fetching the json.
class AllPeople extends StatefulWidget {
final String title;
AllPeople(this.title);
#override
AllPeopleState createState() => AllPeopleState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Listviews"),
),
);
}
class AllPeopleState extends State<AllPeople> {
List data;
List<Profile> profiles;
Future<String> getData() async {
var response = await http.get(
Uri.encodeFull("http://test.mallcomm.co.uk/json_feeds/users.json"),
headers: {"Accept": "application/json"});
fetchPeople().then((List<Profile> p) {
this.setState(() {
data = json.decode(response.body);
profiles = p;
});
});
return "Success!";
}
#override
void initState() {
this.getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('CMS Users'),
),
body: ListView.builder(
padding: EdgeInsets.only(top: 20.0, left: 4.0),
itemExtent: 70.0,
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, int index) {
return Card(
elevation: 10.0,
child: InkWell(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new PeopleDetails("Profile Page", profiles[index]),
));
},
child: ListTile(
leading: CircleAvatar(
child: Text(profiles[index].getInitials()),
backgroundColor: Colors.deepPurple,
radius: 30.0,
),
title: Text(
data[index]["firstname"] + "." + data[index]["lastname"]),
subtitle: Text(
data[index]["email"] + "\n" + data[index]["phonenumber"]),
),
),
);
}),
);
}
}
Future<List<Profile>> fetchPeople() async {
try {
http.Response response =
await http.get('http://test.mallcomm.co.uk/json_feeds/users.json');
List<dynamic> responseJson = json.decode(response.body);
List<Profile> profileList =
responseJson.map((d) => new Profile.fromJson(d)).toList();
profileList.sort((a, b) {
return a.lastName.toLowerCase().compareTo(b.lastName.toLowerCase());
});
return profileList;
} catch (e) {
print(e.toString());
}
return null;
}
I then have my "User profile" class which is storing my json Profile
class Profile {
final String firstName;
final String lastName;
final String phoneNumber;
final String userEmail;
bool verifiedValue = false;
bool approvedValue = false;
bool securityApprovedValue = false;
bool blockedValue = false;
Profile({this.firstName, this.lastName, this.phoneNumber, this.userEmail});
factory Profile.fromJson(Map<String, dynamic> json) {
return new Profile(
firstName: json["firstname"],
lastName: json["lastname"],
phoneNumber: json["phonenumber"],
userEmail: json["email"],
);
}
I've tried to do something like
profileList.sort((a,b) {
return a.lastName.toLowerCase().compareTo(b.lastName.toLowerCase());
});
just before I return profileList but it didn't work. I've tried looking at some different examples but If i'm honest I don't understand it too well.

The sort function you suggested does seem to work as you'd expect (but, of course, only compares last name - you might want to compare first name if the last names are equal). I tidied up a bit, to produce this working example:
import 'dart:convert';
import 'dart:async';
import 'package:http/http.dart' as http;
main() async {
fetchPeople().then((list) {
list.forEach(print);
});
}
Future<List<Profile>> fetchPeople() async {
try {
http.Response response =
await http.get('http://test.mallcomm.co.uk/json_feeds/users.json');
List<dynamic> responseJson = json.decode(response.body);
List<Profile> profileList =
responseJson.map((d) => new Profile.fromJson(d)).toList();
profileList.sort((a, b) {
return a.lastName.toLowerCase().compareTo(b.lastName.toLowerCase());
});
return profileList;
} catch (e) {
print(e.toString());
}
}
class Profile {
final String firstName;
final String lastName;
final String phoneNumber;
final String userEmail;
bool verifiedValue = false;
bool approvedValue = false;
bool securityApprovedValue = false;
bool blockedValue = false;
Profile({this.firstName, this.lastName, this.phoneNumber, this.userEmail});
factory Profile.fromJson(Map<String, dynamic> json) {
return new Profile(
firstName: json["firstname"],
lastName: json["lastname"],
phoneNumber: json["phonenumber"],
userEmail: json["email"],
);
}
#override
String toString() {
return 'Profile: $firstName $lastName';
}
}
Here's a State example that works.
class _MyHomePageState extends State<MyHomePage> {
List<Profile> profiles = [];
#override
void initState() {
super.initState();
_refresh();
}
void _refresh() {
fetchPeople().then((list) {
setState(() {
profiles = list;
});
});
}
Future<List<Profile>> fetchPeople() async {
try {
http.Response response =
await http.get('http://test.mallcomm.co.uk/json_feeds/users.json');
List<dynamic> responseJson = json.decode(response.body);
List<Profile> profileList =
responseJson.map((d) => new Profile.fromJson(d)).toList();
profileList.sort((a, b) {
return a.lastName.toLowerCase().compareTo(b.lastName.toLowerCase());
});
return profileList;
} catch (e) {
print(e.toString());
return [];
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new ListView.builder(
itemBuilder: (context, i) => new Text('${profiles[i].firstName} ${profiles[i].lastName}'),
itemCount: profiles.length,
),
);
}
}

Related

How to fetch and show data from a json file which has a list of nested maps

I'm trying to fetch and show data from the json file which contains a list of nested maps, as a beginner I'm facing lot of difficulties while coding it, please help me to fetch and show data from the json file. I don't know how to fetch data, I have to show the name, email, city, age etc in the App UI. I don't know what is the procedure to work this nested maps. Help me to make this code work.
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:http/http.dart';
import 'package:task/model/model_class.dart';
class EmployeeListView extends StatefulWidget {
#override
_EmployeeListViewState createState() => _EmployeeListViewState();
}
class _EmployeeListViewState extends State<EmployeeListView> {
List<Results> _results = List<Results>();
#override
void initState() {
super.initState();
fetchResults.then((value){
setState(() {
_results.addAll(value);
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Employee"),
backgroundColor: Colors.black,
),
body: ListView.builder(
itemCount: 10,
itemBuilder: (context, index){
return Card(
color: Colors.white,
shadowColor: Colors.black,
elevation: 4.5,
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 25.0,
backgroundImage: NetworkImage("url"),
),
title: Text("Name"),
subtitle: Text("Email"),
trailing: IconButton(icon: Icon(Icons.call), onPressed: (){}),
),
);
}),
);
}
Future<List<Results>> fetchResults() async{
var url = "https://randomuser.me/api?page=2&results=10&seed=99d7541361f1e116";
var response = await http.get(url);
if(response.statusCode == 200){
var resultsJson = json.decode(response.body);
for(var resultsJson in resultsJson){
_results.add(Results.fromJson(resultsJson));
return _results;
}
}
}
}
I can see you made a mistake somewhere in your for loop.
for(var resultsJson in resultsJson){
_results.add(Results.fromJson(resultsJson));
return _results;
You used the JsonList(resultsJson) to represent a Json object in the list.
Declare a new list too, and return outside the loop. Change this to;
List<Results> resultsList = [];
for(var result in resultsJson){
resultsList.add(Results.fromJson(result));
}
return resultsList;
Try that out and give feedback please.
Okay according to your code in init state. i don't recommend that you use setState in initState but rather inside didChangeDependences.
You have to decode the json data from the http request
From response its returning the [result] and [info]
I have use the result section and provided the details
Step 1:
class Results {
String gender;
String phone;
String nat;
DocumentReference reference;
Results(this.gender, this.phone, this.nat);
factory Results.fromSnapshot(DocumentSnapshot snapshot) {
Results newEmployee = Results.fromJson(snapshot.data());
newEmployee.reference = snapshot.reference;
return newEmployee;
}
factory Results.fromJson(Map<String, dynamic> json) =>
_resultsFromJson(json);
Map<String, dynamic> toJson() => _resultsToJson(this);
#override
String toString() => 'employeeName ${Results}';
}
Results _resultsFromJson(Map<String, dynamic> data) {
return Results(
data['gender'],
data['phone'],
data['nat'],
);
}
Map<String, dynamic> _resultsToJson(Results instance) {
return {
'gender': instance.gender,
'phone': instance.phone,
'nat': instance.nat,
};
}
Step 2:
List<Results> collectionData = [];
#override
void initState() {
super.initState();
fetchResults().then((value) {
setState(() {
collectionData.addAll(value);
});
});
}
Future<List<Results>> fetchResults() async {
List<Results> _results = [];
var url =
"https://randomuser.me/api?page=2&results=10&seed=99d7541361f1e116";
var response = await http.get(url);
if (response.statusCode == 200) {
var resultsJson = json.decode(response.body)['results'].cast<Map<String,dynamic>>();
await Future.forEach(resultsJson, (element) {
_results.add(Results.fromJson(element));
});
}
return Future.value(_results);
}

Flutter FutureBuilder with REST JSON paging

I take JSON data to Future<List<Data>> _DataList; with this method
and URL like https://nomer.biz.ua/mobile/kievstar?page=1
Future<List<Data>> getData(int pageCount) async {
String url = Uri.encodeFull("https://nomer.biz.ua/mobile/kievstar?page=$pageCount");
var response = await http.get(url, headers: {"Accept": "application/json"}).timeout(const Duration(seconds: 10));
final Map res = json.decode(response.body);
Response model = Response.fromJson(res);
page++;
return model.data;
}
And pass them to FutureBuilder
#override
Widget build(BuildContext context) {
return Scaffold(
body:FutureBuilder(
future: _DataList,
builder: (BuildContext ctx, AsyncSnapshot<dynamic> snapshot){
if (snapshot.connectionState != ConnectionState.done) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text("Error"));
}
if (!snapshot.hasData) {
return Center(child: Text("Error"));
}
var dataToShow = snapshot.data;
return ListView.builder(
controller: _controller,
itemCount: dataToShow == null ? 0 : dataToShow.length,
itemBuilder: (context, index) {
final item = dataToShow[index];
return Card(
//SHOW DATA
);
});
}
)
);
}
Invoke new page on
#override
void initState() {
_DataList = getData(page);
super.initState();
_controller.addListener(() {
if (_controller.position.pixels == _controller.position.maxScrollExtent) {
_DataList= getData(page);
}
});
}
The first page is displayed, but others are not processed. I load a new page, at the moment of scrolling the list to its last element. _DataList = getData(page); receives JSON data from 2 pages, but does not pass them to FutureBuilder.
I could not find a real example where url page navigation is implemented and FutureBuilder together.
You can copy paste run full code below
For demo purpose, I insert new page's data before old data to better see effect
Step 1: You can parse data to model Payload, you can see full code for detail
Step 2: Insert new data and return _DataList
Step 3: Define _future to avoid unnecessary rebuild
code snippet
Future<List<Datum>> getData(int pageCount) async {
String url =
Uri.encodeFull("https://nomer.biz.ua/mobile/kievstar?page=$pageCount");
var response = await http.get(url, headers: {
"Accept": "application/json"
}).timeout(const Duration(seconds: 10));
Payload payload = payloadFromJson(response.body);
_DataList.insertAll(0, payload.data);
page++;
return _DataList;
}
#override
void initState() {
_future = getData(page);
super.initState();
_controller.addListener(() {
if (_controller.position.pixels == _controller.position.maxScrollExtent) {
setState(() {
_future = getData(page);
});
}
});
}
FutureBuilder(
future: _future,
working demo
full code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));
String payloadToJson(Payload data) => json.encode(data.toJson());
class Payload {
Payload({
this.currentPage,
this.data,
this.firstPageUrl,
this.from,
this.lastPage,
this.lastPageUrl,
this.nextPageUrl,
this.path,
this.perPage,
this.prevPageUrl,
this.to,
this.total,
});
int currentPage;
List<Datum> data;
String firstPageUrl;
int from;
int lastPage;
String lastPageUrl;
String nextPageUrl;
String path;
int perPage;
dynamic prevPageUrl;
int to;
int total;
factory Payload.fromJson(Map<String, dynamic> json) => Payload(
currentPage: json["current_page"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
firstPageUrl: json["first_page_url"],
from: json["from"],
lastPage: json["last_page"],
lastPageUrl: json["last_page_url"],
nextPageUrl: json["next_page_url"],
path: json["path"],
perPage: json["per_page"],
prevPageUrl: json["prev_page_url"],
to: json["to"],
total: json["total"],
);
Map<String, dynamic> toJson() => {
"current_page": currentPage,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
"first_page_url": firstPageUrl,
"from": from,
"last_page": lastPage,
"last_page_url": lastPageUrl,
"next_page_url": nextPageUrl,
"path": path,
"per_page": perPage,
"prev_page_url": prevPageUrl,
"to": to,
"total": total,
};
}
class Datum {
Datum({
this.id,
this.nomerT,
this.datumOperator,
this.ourPrice,
});
int id;
String nomerT;
Operator datumOperator;
int ourPrice;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
nomerT: json["nomer_t"],
datumOperator: operatorValues.map[json["operator"]],
ourPrice: json["our_price"],
);
Map<String, dynamic> toJson() => {
"id": id,
"nomer_t": nomerT,
"operator": operatorValues.reverse[datumOperator],
"our_price": ourPrice,
};
}
enum Operator { KV }
final operatorValues = EnumValues({"kv": Operator.KV});
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;
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int page = 1;
List<Datum> _DataList = [];
Future<List<Datum>> _future;
ScrollController _controller = ScrollController();
Future<List<Datum>> getData(int pageCount) async {
String url =
Uri.encodeFull("https://nomer.biz.ua/mobile/kievstar?page=$pageCount");
var response = await http.get(url, headers: {
"Accept": "application/json"
}).timeout(const Duration(seconds: 10));
Payload payload = payloadFromJson(response.body);
_DataList.insertAll(0, payload.data);
page++;
return _DataList;
}
#override
void initState() {
_future = getData(page);
super.initState();
_controller.addListener(() {
if (_controller.position.pixels == _controller.position.maxScrollExtent) {
setState(() {
_future = getData(page);
});
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _future,
builder: (BuildContext ctx, AsyncSnapshot<List<Datum>> snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text("Error"));
}
if (!snapshot.hasData) {
return Center(child: Text("Error"));
}
var dataToShow = snapshot.data;
return ListView.builder(
controller: _controller,
itemCount: dataToShow == null ? 0 : dataToShow.length,
itemBuilder: (context, index) {
final item = dataToShow[index];
return Card(
child: ListTile(
title: Text(dataToShow[index].id.toString()),
subtitle: Text(dataToShow[index].ourPrice.toString()),
),
);
});
}));
}
}

How to extract a List form a JSON in flutter?

So, I am pretty new to async programming in flutter, I came across a json fine which looks like this:
[{
"Bus": ["a", "b", "c"],
"Stops": ["1", "2", "3", "4"]
}]
So, I made a class:
class StopInfo {
final List Bus;
final List Stop;
StopInfo({this.Bus, this.Stop});
factory StopInfo.fromJson(Map<String, dynamic> json) {
return StopInfo(
busNames: json["Bus"],
busStops: json["Stops"]
);
}
}
Now, if I am fetching Data like this:
Future<StopInfo> fetchStopData() async {
var response = await http.get(url);
print(response.body);
StopInfo _stopInfo = StopInfo();
if (response.statusCode == 200) {
/*
What do I do here
*/
} else {
throw Exception('Failed to get data');
}
}
I am confused what to do here, Should I change something else?
Thanks in advance.
here is a simple example which shows how you can extract and use JSON data:
import "package:flutter/material.dart";
import "dart:convert";
import "package:http/http.dart" as http;
class JsonMultyParse extends StatefulWidget {
#override
_JsonMultyParseState createState() => _JsonMultyParseState();
}
class _JsonMultyParseState extends State<JsonMultyParse> {
final String apiURL = 'https://jsonplaceholder.typicode.com/users';
List<dynamic> users = [];
void fetchJSONData() async {
var jsonResponse = await http.get(apiURL);
if (jsonResponse.statusCode == 200) {
final jsonItems =
json.decode(jsonResponse.body).cast<Map<String, dynamic>>();
print(jsonItems[0]["address"]["street"]);
setState(() {
users = jsonItems;
});
for (dynamic user in users) {
print(user["address"]["street"]);
}
} else {
throw Exception('Failed to load data from internet');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Container(
child: Column(
children: <Widget>[
SizedBox(height: 20),
RaisedButton(
onPressed: fetchJSONData,
child: Text("Fetch Data"),
),
Expanded(
child: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return Card(
child: Container(
height: 50,
padding: const EdgeInsets.all(8.0),
child: Text(
users[index]["address"]["street"],
),
),
);
}),
)
],
),
),
));
}
}
Output:
import 'dart:convert';
Future<List<StopInfo>> fetchStopData() async {
var response = await http.get(url);
print(response.body);
StopInfo _stopInfo = StopInfo();
if (response.statusCode == 200) {
var body = jsonDecode(response.body);
if(body is List) //check if it's a List, as per your example I suppose it will always be a list
return List<StopInfo>.from(body.map(map) => StopInfo.fromJson(map));
else if(body is Map) //check if it's a Map
return [StopInfo.fromJson(body)];
} else {
throw Exception('Failed to get data');
}
}
jsonDecode is part of dart:convert and decode a String to a dynamic value (can be a List or a Map) according to the form of the JSON data it decodes, after that you just convert it to List of StopInfo (if thats what you were expecting from the JSON
Add the following Function in your StopInfo class, which will convert jsonbody into List.
List<StopInfo> stopInfoResponseFromJson(String str) {
final jsonData = json.decode(str);
return new List<StopInfo>.from(jsonData.map((x) => StopInfo.fromJson(x)));
}
Use the above function in your fetchStopData function, like following.
String response = jsonEncode(StopInfo.body);
List<StopInfo> stopInfoResponse = stopInfoResponseFromJson(response);
Try this,
Future<StopInfo> fetchStopData() async {
var response = await http.get(url);
print(response.body);
StopInfo _stopInfo = StopInfo();
if (response.statusCode == 200) {
return StopInfo.fromJson(json.decode(response.body.toString())[0]);
} else {
throw Exception('Failed to get data');
}
}
also modify the StopInfo
factory StopInfo.fromJson(Map<String, dynamic> json) {
List<String> buses=List();
List<String> stops=List();
json["Bus"].forEach((bus)=>buses.add(bus));
json["Stops"].forEach((stop)=>stops.add(stop));
return StopInfo(
busNames: buses,
busStops: stops
);
}
Can you try the following. I generated the class using https://app.quicktype.io/
Change your StopInfo class as
// To parse this JSON data, do
//
// final stopInfo = stopInfoFromJson(jsonString);
import 'dart:convert';
class StopInfo {
StopInfo({
this.bus,
this.stops,
});
List<String> bus;
List<String> stops;
factory StopInfo.fromJson(Map<String, dynamic> json) => StopInfo(
bus: List<String>.from(json["Bus"].map((x) => x)),
stops: List<String>.from(json["Stops"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"Bus": List<dynamic>.from(bus.map((x) => x)),
"Stops": List<dynamic>.from(stops.map((x) => x)),
};
}
and to convert back and forth use these functions
List<StopInfo> stopInfoFromJson(String str) => List<StopInfo>.from(json.decode(str).map((x) => StopInfo.fromJson(x)));
String stopInfoToJson(List<StopInfo> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
You probably need to use the first one and use the list to create the display widgets. The following is a minimal example
class _MyHomePageState extends State<MyHomePage> {
String busStops = '''
[{
"Bus": ["a", "b", "c"],
"Stops": ["1", "2", "3", "4"]
}]
''';
List<StopInfo> allStops = [];
List<Widget> cardsList = [];
#override
void initState() {
super.initState();
loadPrelimData();
}
void loadPrelimData(){
setState(() {
allStops.clear();
allStops = stopInfoFromJson(busStops);
fillColumnChildren();
});
}
void fillColumnChildren(){
cardsList.clear();
allStops.forEach((stopInfos) {
String stops = "";
stopInfos.stops.forEach((element) { stops += element + ", "; });
stopInfos.bus.forEach((element) {
cardsList.add(
//the widget that will be displayed
Card(
child: ListTile(title: Text("Bus:" + element),
subtitle: Text("Stops:" + stops),
),
)
);
});
});
}
List<StopInfo> stopInfoFromJson(String str) => List<StopInfo>.from(json.decode(str).map((x) => StopInfo.fromJson(x)));
String stopInfoToJson(List<StopInfo> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Bus stops"),),
body: Center(
child: Column(children: cardsList)
));
}
}
I get the following
You model
class StopInfo {
final List<String> busList;
final List<String> stopList;
StopInfo({
this.busList,
this.stopList,
});
StopInfo copyWith({
List<String> busList,
List<String> stopList,
}) {
return StopInfo(
busList: busList ?? this.busList,
stopList: stopList ?? this.stopList,
);
}
Map<String, dynamic> toMap() {
return {
'busList': busList,
'stopList': stopList,
};
}
static StopInfo fromMap(Map<String, dynamic> map) {
if (map == null) return null;
return StopInfo(
busList: List<String>.from(map['busList']),
stopList: List<String>.from(map['stopList']),
);
}
String toJson() => json.encode(toMap());
static StopInfo fromJson(String source) => fromMap(json.decode(source));
#override
String toString() => 'StopInfo(busList: $busList, stopList: $stopList)';
#override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is StopInfo &&
listEquals(o.busList, busList) &&
listEquals(o.stopList, stopList);
}
#override
int get hashCode => busList.hashCode ^ stopList.hashCode;
}
Your Service
Future<StopInfo> fetchStopData() async {
var response = await http.get(url);
print(response.body);
if (response.statusCode == 200) {
return StopInfo.fromJson(response.body);
} else {
throw Exception('Failed to get data');
}
}

Dart / Flutter JSON parsing and display

Dart / Flutter JSON parsing and display
I am having trouble parsing and displaying the info. Am getting data from API
I get a response == 200 from API but am unable to display it.
The printout on screen is "Instance of medData"
Future<medData> fetchData(http.Client client) async {
final response = await http.get(
'xxxxxxxxxx',
headers: {
"host": "rapidapi.com",
"key": "x87439756734",
},
);
if (response.statusCode == 200) {
// List json = json.decode(response.body);
// return json.map((medData) => new medData.fromJson(medData)).toList();
return medData.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load data from API');
}
}
This Is the List View Builder
ListView _medDataListView(data) {
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return _tile(data[index].cases, data[index].number, Icons.work);
});
}
Tile builder
ListTile _tile(String title, String subtitle, IconData icon) => ListTile(
title: Text(title,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 20,
)),
subtitle: Text(subtitle),
leading: Icon(
icon,
color: Colors.blue[500],
),
);
Class medData for parsing the JSON
class medData {
String country;
List<LatestStatByCountry> latestStatByCountry;
medData({this.country, this.latestStatByCountry});
medData.fromJson(Map<String, dynamic> json) {
country = json['country'];
if (json['latest_stat_by_country'] != null) {
latestStatByCountry = new List<LatestStatByCountry>();
json['latest_stat_by_country'].forEach((v) {
latestStatByCountry.add(new LatestStatByCountry.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['country'] = this.country;
if (this.latestStatByCountry != null) {
data['latest_stat_by_country'] =
this.latestStatByCountry.map((v) => v.toJson()).toList();
}
return data;
}
}
class LatestStatByCountry {
String id;
String countryName;
String totalCases;
String newCases;
String activeCases;
String totalDeaths;
String newDeaths;
String totalRecovered;
String seriousCritical;
Null region;
String totalCasesPer1m;
String recordDate;
LatestStatByCountry(
{this.id,
this.countryName,
this.totalCases,
this.newCases,
this.activeCases,
this.totalDeaths,
this.newDeaths,
this.totalRecovered,
this.seriousCritical,
this.region,
this.totalCasesPer1m,
this.recordDate});
LatestStatByCountry.fromJson(Map<String, dynamic> json) {
id = json['id'];
countryName = json['country_name'];
totalCases = json['total_cases'];
newCases = json['new_cases'];
activeCases = json['active_cases'];
totalDeaths = json['total_deaths'];
newDeaths = json['new_deaths'];
totalRecovered = json['total_recovered'];
seriousCritical = json['serious_critical'];
region = json['region'];
totalCasesPer1m = json['total_cases_per1m'];
recordDate = json['record_date'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['country_name'] = this.countryName;
data['total_cases'] = this.totalCases;
data['new_cases'] = this.newCases;
data['active_cases'] = this.activeCases;
data['total_deaths'] = this.totalDeaths;
data['new_deaths'] = this.newDeaths;
data['total_recovered'] = this.totalRecovered;
data['serious_critical'] = this.seriousCritical;
data['region'] = this.region;
data['total_cases_per1m'] = this.totalCasesPer1m;
data['record_date'] = this.recordDate;
return data;
}
}
Building the widget
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<medData>(
future: fetchData(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text("${snapshot.data}");
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
),
);
}
}
I don't really know what i'm doing wrong when trying to display the data.
You can copy paste run full code below
Step 1 : parse json string with medDataFromJson(response.body);
factory MedData.fromJson(Map<String, dynamic> json) => MedData(
country: json["country"],
latestStatByCountry: List<LatestStatByCountry>.from(
json["latest_stat_by_country"]
.map((x) => LatestStatByCountry.fromJson(x))),
);
Step 2 : In FutureBuilder do return _medDataListView(snapshot.data.latestStatByCountry);
Step 3: ListView _medDataListView(List<LatestStatByCountry> data) data is List<LatestStatByCountry>
working demo
full code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
// To parse this JSON data, do
//
// final medData = medDataFromJson(jsonString);
import 'dart:convert';
MedData medDataFromJson(String str) => MedData.fromJson(json.decode(str));
String medDataToJson(MedData data) => json.encode(data.toJson());
class MedData {
String country;
List<LatestStatByCountry> latestStatByCountry;
MedData({
this.country,
this.latestStatByCountry,
});
factory MedData.fromJson(Map<String, dynamic> json) => MedData(
country: json["country"],
latestStatByCountry: List<LatestStatByCountry>.from(
json["latest_stat_by_country"]
.map((x) => LatestStatByCountry.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"country": country,
"latest_stat_by_country":
List<dynamic>.from(latestStatByCountry.map((x) => x.toJson())),
};
}
class LatestStatByCountry {
String id;
String countryName;
String totalCases;
String newCases;
String activeCases;
String totalDeaths;
String newDeaths;
String totalRecovered;
String seriousCritical;
dynamic region;
String totalCasesPer1M;
DateTime recordDate;
LatestStatByCountry({
this.id,
this.countryName,
this.totalCases,
this.newCases,
this.activeCases,
this.totalDeaths,
this.newDeaths,
this.totalRecovered,
this.seriousCritical,
this.region,
this.totalCasesPer1M,
this.recordDate,
});
factory LatestStatByCountry.fromJson(Map<String, dynamic> json) =>
LatestStatByCountry(
id: json["id"],
countryName: json["country_name"],
totalCases: json["total_cases"],
newCases: json["new_cases"],
activeCases: json["active_cases"],
totalDeaths: json["total_deaths"],
newDeaths: json["new_deaths"],
totalRecovered: json["total_recovered"],
seriousCritical: json["serious_critical"],
region: json["region"],
totalCasesPer1M: json["total_cases_per1m"],
recordDate: DateTime.parse(json["record_date"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"country_name": countryName,
"total_cases": totalCases,
"new_cases": newCases,
"active_cases": activeCases,
"total_deaths": totalDeaths,
"new_deaths": newDeaths,
"total_recovered": totalRecovered,
"serious_critical": seriousCritical,
"region": region,
"total_cases_per1m": totalCasesPer1M,
"record_date": recordDate.toIso8601String(),
};
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
MedData medData;
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
ListView _medDataListView(List<LatestStatByCountry> data) {
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return _tile(
data[index].countryName, data[index].totalCases, Icons.work);
});
}
ListTile _tile(String title, String subtitle, IconData icon) => ListTile(
title: Text(title,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 20,
)),
subtitle: Text(subtitle),
leading: Icon(
icon,
color: Colors.blue[500],
),
);
Future<MedData> fetchData(http.Client client) async {
final response = await http.get(
'https://coronavirus-monitor.p.rapidapi.com/coronavirus/latest_stat_by_country.php?country=South%20Africa',
headers: {
"x-rapidapi-host": "coronavirus-monitor.p.rapidapi.com",
"x-rapidapi-key": "23bdb74dbfmsh865510b645e32f6p1f7b7bjsn2e800c1ac844",
},
);
/*String jsonString = '''
{ "country": "South Africa", "latest_stat_by_country": [ { "id": "216413", "country_name": "South Africa", "total_cases": "709", "new_cases": "", "active_cases": "697", "total_deaths": "", "new_deaths": "", "total_recovered": "12", "serious_critical": "2", "region": null, "total_cases_per1m": "12", "record_date": "2020-03-26 05:50:02.171" } ] }
''';
http.Response response = http.Response(jsonString, 200);*/
if (response.statusCode == 200) {
// List json = json.decode(response.body);
// return json.map((medData) => new medData.fromJson(medData)).toList();
//return medData.fromJson(json.decode(response.body));
medData = medDataFromJson(response.body);
return medData;
} else {
throw Exception('Failed to load data from API');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<MedData>(
future: fetchData(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasData) {
//return Text("${snapshot.data}");
return _medDataListView(snapshot.data.latestStatByCountry);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
),
);
}
}

can't fetch data api url json flutter

i try to fetch api json id , username , photo ..etc...
and when use jsonplaceholder it's working fine
and when use mine don't get any data
flutter code
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class ListViewJsonapi extends StatefulWidget {
_ListViewJsonapiState createState() => _ListViewJsonapiState();
}
class _ListViewJsonapiState extends State<ListViewJsonapi> {
final String uri = 'https://www.christian-dogma.com/android-index.php';
Future<List<Users>> _fetchUsers() async {
var response = await http.get(uri);
if (response.statusCode == 200) {
final items = json
.decode(utf8.decode(response.bodyBytes))
.cast<Map<String, dynamic>>();
List<Users> listOfUsers = items.map<Users>((json) {
return Users.fromJson(json);
}).toList();
return listOfUsers;
} else {
throw Exception('Failed to load internet');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<Users>>(
future: _fetchUsers(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator());
return ListView(
children: snapshot.data
.map((user) => ListTile(
title: Text(user.name),
subtitle: Text(user.email),
leading: CircleAvatar(
backgroundColor: Colors.red,
child: Text(user.name[0],
style: TextStyle(
fontSize: 18.0,
color: Colors.white,
)),
),
))
.toList(),
);
},
),
);
}
}
class Users {
int id;
String name;
String username;
String email;
Users({
this.id,
this.name,
this.username,
this.email,
});
factory Users.fromJson(Map<String, dynamic> json) {
return Users(
id: json['id'],
name: json['name'],
email: json['email'],
username: json['username'],
);
}
}
when use https://jsonplaceholder.typicode.com/users it's working fine
and when use mine https://www.christian-dogma.com/android-index.php i don't get any data
He managed to make it work, one of the problems he has is that the id asks me to be a String since you had it as an integer, I hope it worked for you.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class JsonApiPhp extends StatefulWidget {
#override
_JsonApiPhpState createState() => _JsonApiPhpState();
}
class _JsonApiPhpState extends State<JsonApiPhp> {
bool loading = true;
final String url = 'https://www.christian-dogma.com/android-index.php';
var client = http.Client();
List<User> users = List<User>();
#override
void initState(){
fetchData();
super.initState();
}
Future<void> fetchData() async {
http.Response response = await client.get(url);
if(response.statusCode == 200){ // Connection Ok
List responseJson = json.decode(response.body);
responseJson.map((m) => users.add(new User.fromJson(m))).toList();
setState(() {
loading = false;
});
} else {
throw('error');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: loading ?
Container(
child: Center(
child: CircularProgressIndicator(),
),
) :
ListView.builder(
itemCount: users.length,
itemBuilder: (BuildContext context, int index){
return Card(
child: ListTile(
title: Text(users[index].username),
),
);
},
)
),
);
}
}
class User {
final String id;
final String name;
final String username;
final String email;
User({
this.id,
this.name,
this.username,
this.email,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
username: json['username'],
);
}
}
I kind of banged my head around and finally found out that your JSON response is returning the id as a string and not as an integer.
Change the factory to following code.
factory Users.fromJson(Map<String, dynamic> json) {
return Users(
id: int.parse(json['id']),
name: json['name'],
email: json['email'],
username: json['username'],
);
Cheers!