I am developing an android application with flutter, what I am doing is displaying a json in an application page. When I run the application it doesn't give me an error but it doesn't show me the data, the json I want to read is the following:
[
{
"deviceid": 27,
"f2cuid": "Estacion1_A",
"devicedata": {
"isRunning": 0,
"color": "w3-red",
"colorNoW3": "red",
"device_name": "Estacion1_A"
}
},
{
"deviceid": 20,
"f2cuid": "B19",
"devicedata": {
"isRunning": 1,
"color": "w3-green",
"colorNoW3": "green",
"device_name": "B19"
}
}
]
It's in my model class:
class Stations {
Int? isRunning;
String? color;
String? colorNoW3;
String? devicename;
Stations(
{this.isRunning,
this.color,
this.colorNoW3,
this.devicename,
});
factory Stations.fromJson(Map<String, dynamic> json) {
return Stations(
isRunning: json['isRunning'],
color: json['color'],
colorNoW3: json['colorNoW3'],
devicename: json['device_name'],
);
}
}
This is my service:
Future<List<Stations>> getStations() async {
Uri url = Uri.parse('URL');
final response = await http.get(url);
var data = jsonDecode(response.body);
print('data: $data');
List<Stations> stations = data.map((e) => Stations.fromJson(e)).toList();
return stations;
}
and this is the way I display it:
return Scaffold(
appBar: AppBar(
title: const Text('Sistema Escolar Administrativo'),
),
drawer: DrawerWidgetMenu(),
body: Container(
child: FutureBuilder(
future: stationSvc.getStations(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Container(
child: Center(
child: Text('No hay datos que mostrar'),
),
);
}
return snapshot.data.length > 0
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: InkWell(
onTap: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => HomePage(),
),
);
},
child: ListTile(
leading: Text(snapshot.data[index].devicename!),
title: Text(snapshot.data[index].color!),
subtitle: Text(snapshot.data[index].colorNoW3!),
),
));
})
: Center(
child: Text('No hay datos, registra un grupo primero'));
}),
),
);
You forgot to specify nested map:
factory Stations.fromJson(Map<String, dynamic> json) {
return Stations(
isRunning: json['devicedata']?['isRunning'],
color: json['devicedata']?['color'],
colorNoW3: json['devicedata']?['colorNoW3'],
devicename: json['devicedata']?['device_name'],
);
}
I am sharing a complete class named SampleModel below which can help to parse JSON in flutter:
class SampleModel {
String? _myName;
bool? _isActive;
SampleModel({String? myName, bool? isActive}) {
if (myName != null) {
_myName = myName;
}
if (isActive != null) {
_isActive = isActive;
}
}
String? get myName => _myName;
set myName(String? myName) => _myName = myName;
bool? get isActive => _isActive;
set isActive(bool? isActive) => _isActive = isActive;
SampleModel.fromJson(Map<String, dynamic> json) {
_myName = json['myName'];
_isActive = json['isActive'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['myName'] = _myName;
data['isActive'] = _isActive;
return data;
}
}
Sample JSON for the same class:
{
"myName" : "Your Name",
"isActive" : true
}
Check if this can help in your case.
your json type is an array, not a map.
look at [ ] syntax on json file.
to deal with an Array, you should make it to a list first:
List<Map<String,dynamic>> mylistofMapformJson = json.decode(receivedJson);
//you should get your list stations like this:
List<Stations> listStationsFromJson = List.generate(
mylistofMapformJson.length,
(index) => Stations.fromJson(mylistofMapformJson));
Related
I want to fetch data from the JSON file to GridView.builder(), I watched a lot of videos but I didn't achieve any results, please help me to do that.
This is the JSON file I want to use: My JSON file here
{
"Ads": {
"show_ads": true,
"InterAd": "unity",
"bannerAd": "unity",
},
"LOCAL_BANNER": {
"show": true,
"image": "image1.jpg",
"url": "https://www.google.com"
},
"MORE_APPS": [{
"title": "Get app now",
"img": "www.google.com",
"url": "www.google.com",
"country": "IN"
}, {
"title": "Get app now",
"img": "www.google.com",
"url": "www.google.com",
"country": ""
}
],
}
I WANT TO fill data to grid view using MORE_APPS key.
Thank you;
1st.. store your json in an asset folder.. preferribly in rootfolder/assets
2.. register your asset in your pubspec.yaml file
3.. create your model.. preferribly using https://app.quicktype.io/dart/.. copy your json data there, and it will generate your model for you.
// To parse this JSON data, do
//
// final myData = myDataFromJson(jsonString);
import 'dart:convert';
MyData myDataFromJson(String str) => MyData.fromJson(json.decode(str));
String myDataToJson(MyData data) => json.encode(data.toJson());
class MyData {
MyData({
this.ads,
this.localBanner,
this.moreApps,
});
Ads? ads;
LocalBanner? localBanner;
List<MoreApp>? moreApps;
factory MyData.fromJson(Map<String, dynamic> json) => MyData(
ads: Ads.fromJson(json["Ads"]),
localBanner: LocalBanner.fromJson(json["LOCAL_BANNER"]),
moreApps: List<MoreApp>.from(json["MORE_APPS"].map((x) => MoreApp.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"Ads": ads!.toJson(),
"LOCAL_BANNER": localBanner!.toJson(),
"MORE_APPS": List<dynamic>.from(moreApps!.map((x) => x.toJson())),
};
}
class Ads {
Ads({
this.showAds,
this.interAd,
this.bannerAd,
});
bool? showAds;
String? interAd;
String? bannerAd;
factory Ads.fromJson(Map<String, dynamic> json) => Ads(
showAds: json["show_ads"],
interAd: json["InterAd"],
bannerAd: json["bannerAd"],
);
Map<String, dynamic> toJson() => {
"show_ads": showAds,
"InterAd": interAd,
"bannerAd": bannerAd,
};
}
class LocalBanner {
LocalBanner({
this.show,
this.image,
this.url,
});
bool? show;
String? image;
String? url;
factory LocalBanner.fromJson(Map<String, dynamic> json) => LocalBanner(
show: json["show"],
image: json["image"],
url: json["url"],
);
Map<String, dynamic> toJson() => {
"show": show,
"image": image,
"url": url,
};
}
class MoreApp {
MoreApp({
this.title,
this.img,
this.url,
this.country,
});
String? title;
String? img;
String? url;
String? country;
factory MoreApp.fromJson(Map<String, dynamic> json) => MoreApp(
title: json["title"],
img: json["img"],
url: json["url"],
country: json["country"],
);
Map<String, dynamic> toJson() => {
"title": title,
"img": img,
"url": url,
"country": country,
};
}
4.. create your function that converts the json data to the model..
import 'package:flutter/services.dart';
Future<MyData> readJsonFile() async {
final String response = await rootBundle.loadString('assets/filejson.json');
final data = myDataFromJson(response);
return data;
}
5.. declare a global variable.. in this case i have named the model MyData.. so declare that globally
MyData data = MyData();
in your initstate make sure to assign your value to the variable data
void initState() {
readJsonFile().then((value) => setState((){
data = value;
}));
super.initState();}
then do the following
FutureBuilder(
future: readJsonFile(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if(snapshot.hasData){
return Center(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
color: Colors.lightGreen,
child: Column(
children: [
Text(
"Ads"
),
Text("show_ads: ${data.ads!.showAds}"),
Text("InterAd : ${data.ads!.interAd}"),
Text("bannerAd: ${data.ads!.bannerAd}")
],
),
),
Container(
color: Colors.amber,
child: Column(
children: [
Text(
"LOCAL_BANNER"
),
Text("show: ${data.localBanner!.show}"),
Text("image: ${data.localBanner!.image}"),
Text("url: ${data.localBanner!.url}"),
],
),
)
],
),
SizedBox(height: 40,),
Expanded(
child: GridView.builder(
itemCount: data.moreApps!.length,
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
childAspectRatio: 3 / 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20),
itemBuilder: (context, index) {
return Container(
child: Column(
children: [
Text(data.moreApps![index].title!),
Text(data.moreApps![index].img!),
Text(data.moreApps![index].url!),
Text(data.moreApps![index].country!),
],
),
);
}),
),
],
)
); }
else{
return const CircularProgressIndicator();
}
},)
I want to get data of inventory but not getting. I am doing API integration without model because there are some issues in Model just to get data and want to display in to my view.
this is my service class of get data through API.
Future<dynamic> getInventory() async {
var data;
String? userId = await preferenceService.getuserId();
String? accessToken = await preferenceService.getAccessToken();
var response = await http.get(Uri.parse('${AppUrl.getInventory}/$userId'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Barear $accessToken'
});
print("The data of the specific inventory ===========>>>>>>>> " +
response.body.toString());
if (response.statusCode == 200) {
data = jsonDecode(response.body);
print('This is futr dsta --->>> $data');
} else {
data=[];
}
return data;
}
This is my controller class where i am using above service function
Future getMyInvenoryFromService() async {
try {
isLoadingInventory(true);
await inventoryService.getInventory().then((val) {
if (val != []) {
inventoryData = val;
} else {
inventoryData = [];
}
});
} finally {
isLoadingInventory(false);
}
}
But when i am accessing the data with inventoryData (in controller) i am getting null, but in controller i am getting values when debugging. but i am not understanding why i am receiving null values in view.
This is my view,
class _UserInventoryScreenState extends State<UserInventoryScreen> {
InventoryController inventoryController = Get.put(InventoryController());
InventoryService inventoryService = InventoryService();
GiftController giftController = Get.put(GiftController());
GiftStorageService giftStorageService = GiftStorageService();
#override
void initState() {
super.initState();
/*Future delay() async {
await new Future.delayed(new Duration(milliseconds: 3000), () {
inventoryController.getMyInvenoryFromService();
});
}*/
Timer.run(() {
inventoryController.getMyInvenoryFromService();
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.pinkAppBar,
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
leading: InkWell(
onTap: () {
Get.back();
},
child: Icon(Icons.arrow_back)),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Inventory'),
InkWell(
onTap: () {
Get.to(AddInventoryScreen());
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration:
BoxDecoration(border: Border.all(color: Colors.white)),
child: Text(
"Add Inventory",
style: TextStyle(fontSize: 16),
),
),
)
],
),
),
body: Obx(() {
return inventoryController.isLoadingInventory.value == true
? Center(child: CircularProgressIndicator())
: ElevatedButton(
onPressed: () async {
await inventoryController.getMyInvenoryFromService();
},
child: Text("${inventoryController.inventoryData.length}"),
);
If your response.statusCode isn't 200 it might be because you are setting wrong your headers:
'Authorization': 'Barear $accessToken'
Change it to:
'Authorization': 'Bearer $accessToken'
I am going to create a JSON data in my flutter application and allow users to choice what item that theirs favorite to. This is the class from Doa, and the data i take it from local JSON file.
import 'dart:convert';
List<Doa> doaFromJson(String str) =>
List<Doa>.from(json.decode(str).map((x) => Doa.fromJson(x)));
String doaToJson(List<Doa> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Doa {
Doa({
this.id,
this.grup,
this.judul,
this.lafaz,
this.latin,
this.arti,
this.tentang,
this.mood,
this.tag,
this.fav,
});
final int id;
final String grup;
final String judul;
final String lafaz;
final String latin;
final String arti;
final String tentang;
final String mood;
final String tag;
bool fav;
factory Doa.fromJson(Map<String, dynamic> json) => Doa(
id: json["id"],
grup: json["grup"],
judul: json["judul"],
lafaz: json["lafaz"],
latin: json["latin"],
arti: json["arti"],
tentang: json["tentang"],
mood: json["mood"],
tag: json["tag"],
fav: json["fav"],
);
Map<String, dynamic> toJson() => {
"id": id,
"grup": grup,
"judul": judul,
"lafaz": lafaz,
"latin": latin,
"arti": arti,
"tentang": tentang,
"mood": mood,
"tag": tag,
"fav": fav,
};
}
And this is my main page that show the list of the JSON data.
import 'package:flutter/material.dart';
import 'package:json_test/class/doa.dart';
import 'package:json_test/page/DoaPage.dart';
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
List<Doa> doaList;
bool _isInit = true;
Future<void> fetchDoa(BuildContext context) async {
final jsonstring =
await DefaultAssetBundle.of(context).loadString('assets/doa.json');
doaList = doaFromJson(jsonstring);
_isInit = false;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("JSON Data test"),
),
body: Container(
child: FutureBuilder(
future: _isInit ? fetchDoa(context) : Future(null),
builder: (context, _) {
if (doaList.isNotEmpty) {
return ListView.builder(
itemCount: doaList.length,
itemBuilder: (BuildContext context, int index) {
Doa doa = doaList[index];
return Card(
margin: EdgeInsets.all(8),
child: ListTile(
title: Text(doa.judul),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) =>
DoaPage(
doa: doa,
)));
},
trailing: IconButton(
icon: Icon(
doa.fav
? Icons.favorite
: Icons.favorite_border,
color: doa.fav ? Colors.red : null,
),
onPressed: () =>
setState(() => doa.fav = !doa.fav),
)));
},
);
}
return CircularProgressIndicator();
})));
}
}
The favorite button is worked. But, when I close the application, all of favorited items will be lost.
The result from my code shown here
After I give some 'love' for the items, when I close the app and re-open it, all of favorited items will lost. Anyone can give me some advice for my code? Thank you very much.
You should save the favorite item local phone or you can use apı service. you don't save the that item and when you close the application that item is a coming null
You can use this package for the save favorite item
shared_preferences
or
hive
I am working on a personal Flutter Project which contains a few locally stored JSON Files
This is the code
class CCategory extends StatefulWidget {
#override
_CCategory createState() => _CCategory();
}
class Prod {
String Name;
String Image;
Prod({ this.Name, this.Image});
factory Prod.fromJson(Map<String, dynamic> parsedJson) {
return Prod(
Name: parsedJson['Name'],
Image: parsedJson['Image']);
}
}
Future<String> _loadProdAsset() async {
return await rootBundle.loadString('assets/data/Dabur.json');
}
Future<Prod> loadProd() async {
String jsonString = await _loadProdAsset();
final jsonResponse = json.decode(jsonString);
return new Prod.fromJson(jsonResponse);
}
class _CCategory extends State<CCategory> {
Prod _prod;
bool _loaded = false;
#override
void initState() {
super.initState();
loadProd().then((s) => setState(() {
_prod = s;
_loaded = true;
}));
}
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitDown,
DeviceOrientation.portraitUp,
]);
return MaterialApp(
title: "Dabur Products",
theme: ThemeData(
primaryColor: Colors.black,
),
home: Scaffold(
appBar: AppBar(
title: Text("Dabur Products",
),
),
body: _loaded?Center(
child: ListView(
children: <Widget>[
ListTile(
leading: Image.asset('${_prod.Image}'),
title: Text('${_prod.Name}'),
)
]
)
)
: new Center(
child: new CircularProgressIndicator(),
)
),
);
}
}
The contents of JSON file are not being loaded and this is the error I am encountering in debug
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: type 'List' is not a subtype of type 'Map<String, dynamic>'
Can someone please help me resolve this ?
I don't know how your JSON-file looks like, but looking at your error code, json.decode(jsonString) seem to be giving you a List instead of a Map. I'd guess your JSON-file actually is a list:
[
... content ...
]
Instead, your JSON-file should look something like this (using { }):
{
"Name": ...,
"Image": ...
}
I want to access all the reg_events for the currently logged in user. I have the following code right now
stream: Firestore.instance.collection('users').document(email).snapshots(),
builder: (context, snapshot){
if(!snapshot.hasData){
return Text("Loading..");
}
return Center(
child: new Container(
child: new PageView.builder(
onPageChanged: (value) {
setState(() {
currentpage = value;
});
},
controller: controller,
itemCount: snapshot.data['reg_events'].length,
itemBuilder: (context, index) => builder(index, snapshot.data)),
),
);
}
),
The 'builder' is:
builder(int index, DocumentSnapshot document) {
return new AnimatedBuilder(
animation: controller,
builder: (context, child) {
double value = 1.0;
if (controller.position.haveDimensions) {
value = controller.page - index;
value = (1 - (value.abs() * .5)).clamp(0.0, 1.0);
}
return new Center(
child: new SizedBox(
height: Curves.easeOut.transform(value) * 200,
width: Curves.easeOut.transform(value) * 1000,
child: child,
),
);
},
child: new Card(
child: Text(document.data['reg_events'][0].toString(),
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15, color: Colors.white),),
margin: const EdgeInsets.all(10.0),
color: index % 2 == 0 ? Colors.blue : Colors.red,
),
);
}
But it outputs "Instance of 'DocumentReference'". How do I access this Document Reference?
Maybe it not understand reg_event as List so try this,
stream: Firestore.instance.collection('users').document(email).snapshots(),
builder: (context, snapshot){
List regEvent = new List();
if(snapshot.hasData){
regEvent = snapshot.data['reg_events'];
}
if(!snapshot.hasData){
return Text("Loading..");
}
return Center(
child: new Container(
child: new PageView.builder(
onPageChanged: (value) {
setState(() {
currentpage = value;
});
},
controller: controller,
itemCount: regEvent.length,
itemBuilder: (context, index) {
print(regEvent[index]);
return builder(index, snapshot.data)),}
),
);
}
),
DocumentReference is like a pointer to one document. You can get the single document using .get method which returns Future<DocumentSnapshot>. Since you have an array of them, you can then use Streams to get a bunch of Futures.
List<DocumentReference> references = [ref, ref, ref];
var myStream = Stream.fromFutures(references.map((ref) => ref.get()).toList());
StreamBuilder(builder: ..., stream: myStream);
But...
Firestore has querying, so it should be better if you actually use it. You should be able to reference your reg_events like that:
Firestore.instance.collection('users').document("$email/reg_events").snapshots();
In this example a User object is created which contains a list of references of the entities (or events). This list is then passed to the DatabaseService class which returns a list of EntityDetails stream objects.
DatabaseService Class:
final CollectionReference entityCollection =
Firestore.instance.collection('entities');
final CollectionReference userCollection =
Firestore.instance.collection('user');
Stream<UserDetails> get userDetails {
return userCollection
.document(uid)
.snapshots()
.map(_userDetailsFromSnapshot);
}
UserDetails _userDetailsFromSnapshot(DocumentSnapshot snapshot) {
return UserDetails(
email: snapshot.data['email'],
phone: snapshot.data['phone'],
fname: snapshot.data['fname'],
lname: snapshot.data['lname'],
streetNr: snapshot.data['street_nr'],
city: snapshot.data['city'],
entities: List.from(snapshot.data['entities']));
}
List<Stream<EntityDetails>> getEntitiesFromDRList(
List<DocumentReference> entities) {
List<Stream<EntityDetails>> elist = new List();
entities.forEach((element) {
elist.add(element.snapshots().map((_entityDetailsFromSnapshot)));
});
return elist;
}
EntityDetails _entityDetailsFromSnapshot(DocumentSnapshot snapshot) {
return EntityDetails(
uid: uid,
name: snapshot.data['name'],
description: snapshot.data['description'],
type: snapshot.data['type'],
geoPoint: snapshot.data['geopoint'],
adressString: snapshot.data['adress_string'],
email: snapshot.data['email'],
phone: snapshot.data['phone'],
);}
Widget
stream: DatabaseService(uid: uid).userDetails,
builder: (context, snapshot) {
if (snapshot.hasData) {
UserDetails userDetails = snapshot.data;
//Get the Streams
DatabaseService(uid: uid)
.getEntitiesFromDRList(userDetails.entities)
.forEach((element) {
element.listen((data) {
print("DataReceived: " + data.name);
}, onDone: () {
print("Task Done");
}, onError: (error) {
print("Some Error");
});
});
User-Object
class UserDetails {
final String email;
final String phone;
final String fname;
final String lname;
final String streetNr;
final String city;
final List<DocumentReference> entities;
UserDetails(
{this.email,
this.phone,
this.fname,
this.lname,
this.streetNr,
this.city,
this.entities});
}