json.decode to List<Map<String,dynamic>> issue in flutter - flutter

snap shot from the code
Hello
I am trying to get Data from API
And put it inside List<Map<String,dynamic>>
I use a several ways but they doesn't work
In the image the data saved in the variable but when i use foreach it ignore the index 0
I try to print index 0 and it is ignore it and ignore print (extracted data [0]) and i can't print the length of that list it ignore the print
Their is no errors
Snapshot of the console
I am using flutter 2.8.0
And dart 2.15.0

This is your UI code
class ApiExample extends StatefulWidget {
const ApiExample({Key? key}) : super(key: key);
#override
_ApiExampleState createState() => _ApiExampleState();
}
class _ApiExampleState extends State<ApiExample> {
final items = initAndSet();
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<StackHelp>>(
future: items,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text(snapshot.data.toString()));
}
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) => ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(snapshot.data![index].logo!),
),
title: Text(snapshot.data![index].name!),
),
);
}
return Center(
child: Text("Waiting..."),
);
},
),
);
}
}
This is your API code
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:stackoverflow/model/stackHelp.dart';
Future<List<StackHelp>> initAndSet() async {
const url = "http://muhammeddevxd.pythonanywhere.com/api/ecommerce";
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final Iterable decodeJson = jsonDecode(response.body);
return decodeJson.map((item) => StackHelp.fromJson(item)).toList();
} else {
throw SocketException("No Internet Connection");
}
}
This is your model class
class StackHelp {
int? id;
String? name;
String? logo;
StackHelp({this.id, this.name, this.logo});
StackHelp.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
logo = json['logo'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['logo'] = this.logo;
return data;
}
}
final result is this

Whenever flutter is acting strange, I recommend running the following commands (close the debug session first):
Command 1
flutter clean
Command 2
flutter pub get
If it's still acting strange, it means that the problem is in the code.
Now, your code runs perfectly on my computer, so I'm not sure what the problem is. Although we can try another aproach with it:
Future<void> initAndSet() async {
var url = 'http://muhammeddevxd.pythonanywhere.com/api/ecommerce';
final response = await http.get(Uri.parse(url));
var extractedData =
List<Map<String, dynamic>>.from(jsonDecode(response.body));
extractedData.forEach((element) {
print(element);
});
}
!! Don't forget to import 'dart:convert' and 'package:http/http.dart' as http.

Related

How to get firebase realtime database data in to a list formate in flutter

I am trying to retrieve data from Firebase Realtime Database into a list in Flutter using a model.I don't get snapshot.data how to get data.value. I have read several other posts about using Firebase with Flutter but have not found a clear answer.
Model class screen:
import 'package:firebase_database/firebase_database.dart';
class DataModel {
final String id;
final String name;
final String price;
final String qty;
DataModel(
{required this.id,
required this.name,
required this.price,
required this.qty});
DataModel.fromSnapshot(DataSnapshot snapshot)
: id = snapshot.key.toString(),
name = (snapshot.value as Map<String, dynamic>?)?['productName'] ?? '',
price =
(snapshot.value as Map<String, dynamic>?)?['productPrice'] ?? '',
qty = (snapshot.value as Map<String, dynamic>?)?['qty'] ?? '';
toJson() {
return {
"productName": name,
"productPrice": price,
"qty": qty,
};
}
}
Database service with Firebase query:
import 'package:firebase_database/firebase_database.dart';
import 'package:money_management/data_json_model.dart';
class DatabaseService {
static List<DataModel> getData() {
Query needsSnapshot =
FirebaseDatabase.instance.ref("Money Management").orderByKey();
// print(needsSnapshot); // to debug and see if data is returned
List<DataModel> needs = [];
Map<dynamic, dynamic> values = needsSnapshot.onValue as Map;
values.forEach((key, values) {
needs.add(DataModel.fromSnapshot(values));
});
return needs;
}
}
ListView Page:
import 'package:flutter/material.dart';
import 'package:money_management/data_json_model.dart';
import 'database_service.dart';
class ListScreen extends StatefulWidget {
const ListScreen({Key? key}) : super(key: key);
#override
State<ListScreen> createState() => _ListScreenState();
}
class _ListScreenState extends State<ListScreen> {
List<DataModel> _needs = [];
#override
void initState() {
super.initState();
_setupNeeds();
}
_setupNeeds() async {
List<DataModel> needs = DatabaseService.getData();
setState(() {
_needs = needs;
});
}
#override
Widget build(BuildContext context) {
return RefreshIndicator(
onRefresh: () => _setupNeeds(),
child: ListView.builder(
itemCount: _needs.length,
itemBuilder: (BuildContext context, int index) {
DataModel need = _needs[index];
return Column(
children: [
Text(need.id),
Text(need.name),
Text(need.price),
Text(need.qty),
],
);
}),
);
}
}
Try make the method getData() asynchronous and call get() of FirebaseDatabase instead:
class DatabaseService {
static Future<List<dynamic>> getData() async {
final snapshot = await FirebaseDatabase.instance
.ref("Money Management")
.orderByKey()
.get();
// print(snapshot); // to debug and see if data is returned
List<DataModel> needs = [];
Map<dynamic, dynamic> values = snapshot.value as Map;
values.forEach((key, values) {
needs.add(DataModel.fromSnapshot(values));
});
return needs;
}
}
you can receive data as Map<String,dynamic> in your DataModel like this:
class DataModel {
late String id;
late String name;
late String price;
late String qty;
DataModel({
required this.id,
required this.name,
required this.price,
required this.qty
});
DataModel.fromSnapshot(DataSnapshot snapshot){
Map<String, dynamic> myData= Map<String,dynamic>.from(snapshot.value as
Map);
id = snapshot.key.toString();
name = myData["productName"].toString() ?? '';
price =myData["productPrice"].toString() ?? '';
qty = myData["qty"].toString() ?? '';
}
Map<String,dynamic> toJson() {
return {
"productName": name,
"productPrice": price,
"qty": qty,
};
}
}

Flutter getting data from a map API

hi am new to flutter and i need to get data from a map using API I m struggling at the moment and don't know what to do I always keep getting a error Error '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Iterable'
this is the class code
// To parse this JSON data, do
//
// final aziz = azizFromJson(jsonString);
import 'dart:convert';
Demandes azizFromJson(String str) => Demandes.fromJson(json.decode(str));
String azizToJson(Demandes data) => json.encode(data.toJson());
class Demandes {
Demandes({
required this.srMboSet,
});
SrMboSet srMboSet;
factory Demandes.fromJson(Map<String, dynamic> json) => Demandes(
srMboSet: SrMboSet.fromJson(json["SRMboSet"]),
);
Map<String, dynamic> toJson() => {
"SRMboSet": srMboSet.toJson(),
};
}
class SrMboSet {
SrMboSet({
required this.rsStart,
required this.rsCount,
required this.sr,
});
int rsStart;
int rsCount;
List<Sr> sr;
factory SrMboSet.fromJson(Map<String, dynamic> json) => SrMboSet(
rsStart: json["rsStart"],
rsCount: json["rsCount"],
sr: List<Sr>.from(json["SR"].map((x) => Sr.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"rsStart": rsStart,
"rsCount": rsCount,
"SR": List<dynamic>.from(sr.map((x) => x.toJson())),
};
}
class Sr {
Sr({
required this.rowstamp,
required this.attributes,
});
String rowstamp;
Attributes attributes;
factory Sr.fromJson(Map<String, dynamic> json) => Sr(
rowstamp: json["rowstamp"],
attributes: Attributes.fromJson(json["Attributes"]),
);
Map<String, dynamic> toJson() => {
"rowstamp": rowstamp,
"Attributes": attributes.toJson(),
};
}
class Attributes {
Attributes({
required this.ticketid,
required this.attributesClass,
required this.description,
required this.status,
required this.statusdate,
required this.reportedby,
});
Class ticketid;
Class attributesClass;
Class description;
Class status;
Class statusdate;
Class reportedby;
factory Attributes.fromJson(Map<String, dynamic> json) => Attributes(
ticketid: Class.fromJson(json["TICKETID"]),
attributesClass: Class.fromJson(json["CLASS"]),
description: Class.fromJson(json["DESCRIPTION"]),
status: Class.fromJson(json["STATUS"]),
statusdate: Class.fromJson(json["STATUSDATE"]),
reportedby: Class.fromJson(json["REPORTEDBY"]),
);
Map<String, dynamic> toJson() => {
"TICKETID": ticketid.toJson(),
"CLASS": attributesClass.toJson(),
"DESCRIPTION": description.toJson(),
"STATUS": status.toJson(),
"STATUSDATE": statusdate.toJson(),
"REPORTEDBY": reportedby.toJson(),
};
}
class Class {
Class({
required this.content,
});
String content;
factory Class.fromJson(Map<String, dynamic> json) => Class(
content: json["content"],
);
Map<String, dynamic> toJson() => {
"content": content,
};
}
and this is my main code I always get a error if anyone can help please
// ignore_for_file: use_key_in_widget_constructors, avoid_print, avoid_unnecessary_containers, curly_braces_in_flow_control_structures, prefer_const_constructors, non_constant_identifier_names, unnecessary_new, avoid_function_literals_in_foreach_calls
import 'dart:convert';
import './demandes.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DataFromAPI(),
);
}
}
class DataFromAPI extends StatefulWidget {
#override
_DataFromAPIState createState() => _DataFromAPIState();
}
class _DataFromAPIState extends State<DataFromAPI> {
List<Attributes> MyAllData = [];
#override
void initState() {
loadData();
}
loadData() async {
var response = await http.get(Uri.parse(
'http://192.168.1.30:9080/maxrest/rest/mbo/sr/?_lid=&_lpwd=&_format=json'));
if (response.statusCode == 200) {
String responseBody = response.body;
Map<String, dynamic> jsonBody = json.decode(responseBody);
for (var data in jsonBody) {
MyAllData.add(Attributes(
ticketid: data["ticketid"],
attributesClass: data["attributesClass"],
description: data["description"],
status: data["status"],
statusdate: data["statusdate"],
reportedby: data["reportedby"]));
}
setState(() {
MyAllData.forEach((somedata) => print("Name: ${somedata.ticketid}"));
});
} else {
print("theres something wrong...");
}
}
Widget build(BuildContext context) {
return MaterialApp(
home: new Scaffold(
appBar: AppBar(
title: Text('Liste des SR'),
),
body: MyAllData.length == 0
? new Center(
child: new CircularProgressIndicator(),
)
: showMyUI(),
),
);
}
Widget showMyUI() {
return new ListView.builder(
itemCount: MyAllData.length,
itemBuilder: ((_, index) {
return new Container(
child: new Card(
child: new Container(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(
'Ticket ID : ${MyAllData[index].ticketid}',
),
],
),
),
),
);
}));
}
}
So from your model class, what I see is that you have Attributes inside of Sr, but after your JSON decode, you went ahead to just add data to the attributes list, so that's where your error is coming from, you have not fully deserialised the data here's how you can do it and it would work
loadData() async {
var response = await http.get(Uri.parse(
'http://192.168.1.30:9080/maxrest/rest/mbo/sr/?_lid=&_lpwd=&_format=json'));
if (response.statusCode == 200) {
final jsonBody = json.decode(response.body);
Demandes data = Demandes.fromJson(jsonBody);
final srAttributes = data.srMboSet.sr;
// SR is your list attributes is just an object, So what you do is this
for (int attribute = 0; attribute < srAttributes.length; attribute++) {
MyAllData.add(srAttributes[attribute].attributes);
}
setState(() {
MyAllData.forEach((somedata) => print("Name: ${somedata.ticketid}"));
});
} else {
print("theres something wrong...");
}
}

Display data fetched from JSON API in app

I am developing a Stock app in which I have to display News related to the stocks. I made a News class for the same as well as a factory constructor to convert the data from json
class News {
final String title;
final String desc;
final String imgURL;
final String url;
News(
{required this.title,
required this.desc,
required this.imgURL,
required this.url});
factory News.fromJSON(Map<String, dynamic> json) {
final title = json["title"] as String;
final desc = json["description"] as String;
final imgUrl = json["image_url"] as String;
final url = json["url"] as String;
return News(title: title, desc: desc, imgURL: imgUrl, url: url);
}
}
I have made a method to fetch the data from the API:
Future getNews() async {
final response = await http.get(Uri.parse(
'https://api.stockdata.org/v1/news/all?&filter_entities=true&language=en&api_token=${api_token}&countries=${country}'));
if (response.statusCode == 200) {
final jsonResponse = json.decode(response.body);
return jsonResponse.map((data) => News.fromJSON(data));
} else {
throw Exception('Unexpected error occurred!');
}
}
I am having trouble understanding how I can display the data in my app. I tried using FutureBuilder but I can't seem to understand how it's working.
Any help would be appreciated!
For the FutureBuilder you can do it this way :
FutureBuilder(
future: getNews(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.hasData){
// Save your data in a variable
List<News> news = snapshot.data;
// Create a listview to show all of the news
return newsListView(news); //This is a list
} else {
return Center(
child: Container(
width: 300,
height: 290,
child: Center(child: Text("Error"))
)
);
}
}
),

Add item to provider in flutter

What's the correct way to use provider with an api call?
My current setup, although I don't know if it's correct, is I have a response model and a Response class and the response model gets passed to the response class. the ui is using a provider. Heres's the code:
class InfoProvider extends ChangeNotifier {
Future<Response> getSomeInfo(SomeInfo someInfo) async {
try {
final responseJson = await _provider.post('/info', someInfo.toJson());
ResponseModel someResponse = ResponseModel.fromJson(responseJson['payload']);
return Response.success(someResponse);
} catch (e) {
if (e.toString() == 'refresh_token_not_found') return Response.unauthenticated();
return Response.error(e.getError());
}
}
Future<Response> fetchInfo() async {
try {
final responseJson = await _provider.get('info');
if (responseJson['payload'].isEmpty) return Response.success([]);
AllInfoResponse alLInfoResponse = AllInfoResponse.fromJson(responseJson['payload']);
_allInfo = alLInfoResponse.AllInfoResponse;
return Response.success(alLInfoResponse);
} catch (e) {
if (e.toString() == 'refresh_token_not_found') return Response.unauthenticated();
return Response.error(e.toString());
}
}
}
The ui has a future builder like this: future: Provider.of<InfoProvider>(context).getSomeInfo(),
So that all works, but how can I add some more items to the ui?
Here's my model:
class ResponseModel {
final List<SingleResponseModel> ResponseModel;
ResponseModel({this.ResponseModel});
factory ResponseModel.fromJson(List<dynamic> json) => ResponseModel(
ResponseModel: List<SingleResponseModel>.from(json.map((x) => SingleResponseModel.fromJson(x))),
);
}
class SingleResponseModel {
final String id;
final String title;
SingleResponseModel({
this.id,
this.title,
});
factory SingleResponseModel.fromJson(Map<String, dynamic> json) {
return SingleResponseModel(
id: json['_id'],
title: json['title'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['title'] = this.title;
return data;
}
}
The best way to do this in your scenario is to wrap MaterialApp inside MyApp() in your main.dart file with MultiProvider. Try something like this: https://pub.dev/packages/provider#multiprovider You can place a ChangeNotifierProvider inside it.
Here is how you can access the values of ResponseModel in your UI:
final model=Provider.of<ResponseModel>(context,listen:false);
Don't forget to add getters and setters so that you can use notifyListeners() if you have any ui that depends on it.
This is how your model should look like:
class ResponseModel extends ChangeNotifier {
List<SingleResponseModel> _myModel;
get myModel => _myModel;
set myModel(List<SingleResponseModel> myModel) {
_myModel = myModel;
notifyListeners();
}
}
Here is how you can display your data in a Text Widget (Ideally, you should use Selector instead of Consumer so that the widget only rebuilds if the value its listening to changes):
#override
Widget build(BuildContext context) {
//other widgets
Selector<ResponseModel, int>(
selector: (_, model) => model.myModel,
builder: (_, model, __) {
return ListView.builder(
itemCount: model.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(model[index].title),
subtitle:Text(model[index].id),
);
},
);
}
)
}
Hope this helps! Good Luck!

fetch data by using flutter http request and load more data on scroll down the screen

i fetch data from server using flutter http request and load more data when user scroll to bottom of screen. i receive this error "Unhandled Exception: type 'List' is not a subtype of type 'Product'". Please help, i struggle all day without success.
model.dart file
class Product {
final int id;
final String accountName,
callNumber,
whatsappNumber,
businessLocation,
caption;
final List<Images> productPhoto;
Product({
this.id,
this.accountName,
this.callNumber,
this.whatsappNumber,
this.businessLocation,
this.caption,
this.productPhoto,
});
// this is static method
factory Product.fromJson(Map<String, dynamic> json) {
return Product(
id: json['id'],
accountName: json['account_name'],
callNumber: json['call_number'],
whatsappNumber:
json['whatsapp_number'] != null ? json['whatsapp_number'] : null,
businessLocation: json['business_location'],
caption: json['caption'],
productPhoto:
(json['post_photos'] as List).map((i) => Images.fromJson(i)).toList(),
);
}
}
class Images {
final String filename;
Images({this.filename});
factory Images.fromJson(Map<String, dynamic> json) {
return Images(
filename: json['filename'],
);
}
}
explore.dart file (i import models.dart to this file)
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:windowshoppi/models/global.dart';
import 'package:windowshoppi/models/product.dart';
import 'package:http/http.dart' as http;
class Explore extends StatefulWidget {
#override
_ExploreState createState() => _ExploreState();
}
class _ExploreState extends State<Explore> {
ScrollController _scrollController = ScrollController();
List<Product> data;
String nextUrl;
#override
void initState() {
// TODO: implement initState
super.initState();
this.fetchProduct(http.Client(), ALL_PRODUCT_URL);
_scrollController.addListener(() {
// print(_scrollController.position.pixels);
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
if (nextUrl != null) {
this.fetchProduct(http.Client(), nextUrl);
}
// print(nextUrl);
}
});
}
Future<List<Product>> fetchProduct(http.Client client, url) async {
final response = await client.get(url);
if (response.statusCode == 200) {
Map<String, dynamic> mapResponse = json.decode(response.body);
nextUrl = mapResponse['next'];
if (mapResponse["count"] != "") {
final products = mapResponse["results"].cast<Map<String, dynamic>>();
final listOfProducts = await products.map<Product>((json) {
return Product.fromJson(json);
}).toList();
// return listOfProducts;
setState(() {
data.add(listOfProducts);
});
} else {
return [];
}
} else {
throw Exception('failed to load data from internet');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('http get'),
),
body: ListView.builder(
controller: _scrollController,
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Container(
height: 200,
color: Colors.blue,
child: Text(data[index].caption),
),
);
},
),
);
}
}
Have a look at this part of the code.
final listOfProducts = await products.map<Product>((json) {
return Product.fromJson(json);
}).toList();
In the .map() method you are casting it to type < Product >. So judging by the error you have mentioned, "Unhandled Exception: type 'List' is not a subtype of type Product"
I think the json data being returned contains a List, instead of the product fields. I would highly recommend you to once check the json data being returned, and double-check if you are targeting the correct JSON tree nodes.
Let me know if this solved the issue.