Flutter: Access data from JSON file & convert it to Object - dart

I've following Json stored inside Assets/JSON/example.json
[
{"optiontext" : "One", "optionvalue" : "One"},
{"optiontext" : "Two", "optionvalue" : "Two"},
{"optiontext" : "Three", "optionvalue" : "Three"}
]
I want to read JSON from this file & convert it to MyObject.
Have to use it in Flutter App

Here is sample code snippet for your case. Basically, we can use dartson package for converting.
import 'package:dartson/dartson.dart';
void main(List<String> args) {
String jsonString = '[{"optiontext" : "One", "optionvalue" : "One"},{"optiontext" : "Two", "optionvalue" : "Two"},{"optiontext" : "Three", "optionvalue" : "Three"}]';
var dson = new Dartson.JSON();
List<MyObject> result = dson.decode(jsonString, new MyObject(), true);
print(result[1].optionValue);
}
#Entity()
class MyObject {
#Property(name:"optiontext")
String optionText;
#Property(name:"optionvalue")
String optionValue;
}
As you can't use dartson in flutter due to some issue, the below code snippet can be used with the help of dart:convert
import 'dart:convert';
void main(List<String> args) {
String jsonString = '[{"optiontext" : "One", "optionvalue" : "Value"},{"optiontext" : "Two", "optionvalue" : "Two"},{"optiontext" : "Three", "optionvalue" : "Three"}]';
List<Map> parsedJson = JSON.decode(jsonString);
List<MyObject> result = parsedJson.map((item) => new MyObject.fromJson(item)).toList();
print(result[0].optionText);
print(result[0].optionValue);
}
class MyObject {
String optionText;
String optionValue;
MyObject.fromJson(Map jsonMap)
: optionText = jsonMap['optiontext'],
optionValue = jsonMap['optionvalue'];
}

Here is my solution
I have the following json
[
{
"name": "Abhijit Sawant",
"age": "23",
"height":"180",
"gender": "male",
"hair_color": "black"
},
{
"name": "Akku Sawant",
"age": "23",
"height":"150",
"gender": "male",
"hair_color": "brown"
},
{
"name": "Pikki Sawant",
"age": "23",
"height":"120",
"gender": "male",
"hair_color": "grey"
},
{
"name": "Chikki Sawant",
"age": "23",
"height":"100",
"gender": "female",
"hair_color": "white"
}
]
Following is my Flutter Code
class HomePage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return HomePageState();
}
}
class HomePageState extends State<HomePage>{
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Loading Json"),),
body: Container(
child: Center(
child: FutureBuilder(builder: (context,snapshot){
var myData = json.decode(snapshot.data.toString());
return new ListView.builder(
itemCount: myData == null ? 0: myData.length,
itemBuilder: (BuildContext context,int index){
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text("Name: "+myData[index]["name"]),
Text("Age: "+myData[index]["age"]),
Text("Height: "+myData[index]["height"]),
Text("Gender: "+myData[index]["gender"]),
],
),
);
},);
},
future: DefaultAssetBundle.of(context).loadString("person.json"),),
),
),
);
}
}

Related

I need this object inside the map, but i cant get it

I have this list of maps, and i need to get the 'transactions' value:
final assets = [
{
"name": "BRL", "balance": 150.2,
"transactions" : Transaction(from: "someone", amount: 1)
},
{
"name": "US", "balance": 1100.2,
"transactions" : Transaction(from: "someone", amount: 5)
},
];
i tried to do assets[0]['transactions'], but all i got was null or Instance of 'Transaction'
the class:
class Transaction {
final String id = Random().toString();
final String from;
final double amount;
Transaction({
required this.from,
required this.amount,
});
}
im kinda newbie, then pls help me :)
You can use this dartpad example to view this in an app
Assuming you would like to show your data in a list (since this is a list of maps per the question)
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
itemCount: assets.length,
itemBuilder: (context, index) {
Transaction data = assets[index]['transactions'];
return
ListTile(
leading: Text(data.amount.toString()),
title: Text(data.from.toString()));
});
}
}

why it's returning null value after parsing json + using bloc pattern

I'm Trying to apply BLoC pattern on my code which is simply generate categories to grid View , but some how it's not working although I did the same in this article but without using api instead I used local Json File.
here is the Category_Model
class CategoryModel {
List<_Category> _Categories = [];
CategoryModel.fromJson(Map<String, dynamic> parsedJson) {
print(parsedJson['Categories'].length);
List<_Category> temp = [];
for (int i = 0; i < parsedJson['Categories'].length; i++) {
//_Category is the constructor of _Category Class line number 21
_Category category = _Category(parsedJson['Categories'][i]);
temp.add(category);
}
_Categories = temp;
}
List<_Category> get categories => _Categories;
}
class _Category {
int _id;
String _name;
String _iconPath;
_Category(category) {
_id = category['id'];
_name = category['name'];
_iconPath = category['iconPath'];
}
int get id => _id;
String get name => _name;
String get iconPath => _iconPath;
}
and here where it's comming null
Future<CategoryModel> fetchCategoryList() async {
final jsonCategory = await rootBundle.loadString("assets/CategoryList.json");
final mapJsonCategory = Map.from(jsonDecode(jsonCategory));
return CategoryModel.fromJson(mapJsonCategory);
}
here is the Category_List.dart
import 'package:flutter/material.dart';
import '../blocs/category_bloc.dart';
import '../models/category_model.dart';
class CategoryList extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return CategoryListState();
}
}
class CategoryListState extends State<CategoryList> {
#override
void initState() {
super.initState();
bloc.fetchAllCategoryList();
}
#override
void dispose() {
bloc.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Mazaya'),
),
body: StreamBuilder(
stream: bloc.allCategories,
builder: (context, AsyncSnapshot<CategoryModel> snapshot) {
if (snapshot.hasData) {
return buildList(snapshot);
} else if (snapshot.hasError) {
return Text(snapshot.error.toString());
}
return Center(child: CircularProgressIndicator());
},
),
);
}
Widget buildList(AsyncSnapshot<CategoryModel> snapshot) {
return GridView.builder(
itemCount: snapshot.data.categories.length,
);
}
}
JSON FILE
{
"Categories": [
{
"id": 1,
"name": "Restruants",
"iconPath": " "
},
{
"id": 2,
"name": "Car Rental",
"iconPath": " "
},
{
"id": 3,
"name": "Furniture",
"iconPath": " "
},
{
"id": 4,
"name": "cars",
"iconPath": " "
},
{
"id": 5,
"name": "Maintenance",
"iconPath": " "
},
{
"id": 6,
"name": "Education",
"iconPath": " "
},
{
"id": 7
"name": "Finess",
"iconPath": " "
},
{
"id": 8,
"name": "Electronics",
"iconPath": " "
},
{
"id": 9,
"name": "Medical",
"iconPath": " "
},
{
"id": 10,
"name": "Entirtainment",
"iconPath": " "
}
]
}
I expected the result will lock like the app in this article https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1
Hi First of all correct your json by adding comma after number 7 like this => "id": 7,
Then change fetchMovieList() method in MovieApiProvider as below where we get file from asset with the help of "DefaultAssetBundle":
Future<ItemModel> fetchMovieList(BuildContext context) async {
// final jsonCategory = await rootBundle.loadString("assets/CategoryList.json");
final jsonCategory = await DefaultAssetBundle
.of(context)
.loadString('assets/CategoryList.json');
print(jsonCategory);
final mapJsonCategory = Map<String, dynamic>.from(jsonDecode(jsonCategory));
print(mapJsonCategory);
return ItemModel.fromJson(mapJsonCategory);
}
Then declare your json file in pubspec.yaml as below:
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
assets:
- assets/CategoryList.json
Then change buildList method in your dart file as below:
Widget buildList(AsyncSnapshot<ItemModel> snapshot) {
return GridView.builder(
itemCount: snapshot.data.categories.length,
gridDelegate:
new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return Text(snapshot.data.categories[index].name);
});
}
It will work :)

Flutter reading from JSON if value matches

I have a json of customers:
customer.json
[
{
"name": "Customer 1",
"id": "1"
},
{
"name": "Customer 2",
"id": "2"
},
{
"name": "Customer 3",
"id": "3"
}
]
This is the dart file using this json data:
customerslist.dart
Future Method
Future<String> loadCustomers() async{
var res = await http.get(
Uri.encodeFull(url),
headers: {"Accept": "application/json"});
return res.body;
}
Widget
widgets.add(new FutureBuilder(
future: loadCustomers(),
builder: (context, snapshot){
if(snapshot.hasData){
//get snapshot data from JSON tree
var jsondecode = json.decode(snapshot.data);
return new ListView.builder(
shrinkWrap: true,
itemCount: jsondecode.length,
itemBuilder: (context, index){
String name = jsondecode[index]["name"];
String id = jsondecode[index]["id"];
if(name == "Customer 2"){
return new Column(
children: <Widget>[
new ListTile(
title: new Text("Name"),
trailing: new Text(name),
),
new ListTile(
title: new Text("ID"),
trailing: new Text(id),
)
],
);
}
});
}else{
return new Center(
child: new CircularProgressIndicator(),
);
}
}));
What I am trying to do is bringing out the values if the name matches as you can see from if(name == "Customer 2").
But the problem I am having is:
When i change the if statement to if(name == "Customer 1"), the output is as you would expect:
But if i were to change it to if(name == "Customer 2"), the output turns out blank as such:
Could someone explain why is it turning out like this or is there another method I could go about doing to fix this issue?
I think it's because Column widget is taking full height. You could try using the minimum height for your column and add else condition.
if(name == "Customer 2"){
return new Column(
children: <Widget>[
new ListTile(
title: new Text("Name"),
trailing: new Text(name),
),
new ListTile(
title: new Text("ID"),
trailing: new Text(id),
)
],
);
} else {
return new Container();
}
When you use 'Customer 1' it works fine because your first element is 'Customer 1' , probably you have an error on your console because for other items there are no returning widgets.
In the case of 'Customer 2' the first item is not returned, so check your console log.
itemBuilder expects you return a widget for all the cases.
You just convert the var string to list
var jsondecode = json.decode(snapshot.data);
List list = jsondecode;
String name = list[index]["name"];
String id = list[index]["id"];
then pass the list to get the index may be this will work bocasue the var type may be get the first json string only
enter code here

Flutter data != null

I have a JSON app calling users but I am having problems dealing with null Maps.
This is the Json file.
MemberInfo.json
{
"Dependents": [
{
"Name": "Kim",
"Relationship": "Parent",
"Entitlements": {
"GP": {
"Entitlement": "10000",
"Utilisation": "500",
"Balance": "9500"
},
"OPS": {
"Entitlement": "10000",
"Utilisation": "500",
"Balance": "9500"
},
"IP": {
"Entitlement": "50000",
"Utilisation": "17000",
"Balance": "33000"
}
}
},
{
"Name": "Tim",
"Relationship": "Spouse",
"Entitlements": {
"GP": {
"Entitlement": "10000",
"Utilisation": "500",
"Balance": "9500"
},
"OPS": {
"Entitlement": "10000",
"Utilisation": "500",
"Balance": "9500"
},
"IP": {
}
}
}
]
}
And the dart file is as follows:
import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:async';
import 'package:http/http.dart' as http;
final String url = "http://crm.emastpa.com.my/MemberInfo.json";
final String url2 = "http://crm.emastpa.com.my/MemberInfo2.json";
class Dependents extends StatelessWidget {
Dependents({Key key, this.index, this.name, this.page}) : super(key:key);
final int index;
final String name;
final int page;
Future<String> jsonContent() async {
var res = await http.get(
Uri.encodeFull(url2),
headers: {"Accept": "application/json"});
return res.body;
}
#override
Widget build(BuildContext context) {
Widget fifthBody = new Container(
child: new Center(
child: new FutureBuilder<String>(
future: jsonContent(),
builder: (context, snapshot){
if(snapshot.hasData){
List<Widget> widgets = [];
//get snapshot data from JSON tree
var jsondecode = json.decode(snapshot.data);
//[]->Entitlements
var jsonEntData = jsondecode["Dependents"][index]["Entitlements"];
//Everything under Entitlements
var jsonEntDataGP = jsonEntData["GP"];
var jsonEntDataOPS = jsonEntData["OPS"];
var jsonEntDataIP = jsonEntData["IP"];
//GP Branch
var gp_ent = jsonEntDataGP["Entitlement"];
var gp_util = jsonEntDataGP["Utilisation"];
var gp_bal = jsonEntDataGP["Balance"];
//OPS branch
var ops_ent = jsonEntDataOPS["Entitlement"];
var ops_util = jsonEntDataOPS["Utilisation"];
var ops_bal = jsonEntDataOPS["Balance"];
//IP branch
var ip_ent = jsonEntDataIP["Entitlement"];
var ip_util = jsonEntDataIP["Utilisation"];
var ip_bal = jsonEntDataIP["Balance"];
jsonEntDataGP != null?
widgets.add(new ExpansionTile(
title: new Text("GP"),
children: <Widget>[
new ListTile(
title: new Text("Entitlement"),
trailing: new Text(gp_ent),
)
],
))
: new Center();
jsonEntDataOPS != null?
widgets.add(new ExpansionTile(
title: new Text("OPS"),
children: <Widget>[
new ListTile(
title: new Text("Entitlement"),
trailing: new Text(ops_ent),
)
]))
: new Center();
jsonEntDataIP != null?
widgets.add(new ExpansionTile(
title: new Text("IP"),
children: <Widget>[
new ListTile(
title: new Text("Entitlement"),
trailing: new Text(ip_ent),
)
]))
: new Center();
return new Column(
children: widgets,
);
}else if(snapshot.hasError){
return new Text(snapshot.error);
}
//loading the page
return new Center(
child: new CircularProgressIndicator(),
);
}),
),
);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("$name + index: $index"),
),
body: fifthBody
),
);
}
}
This is the error I am getting:
I/flutter ( 8842): The following assertion was thrown building FutureBuilder<String>(dirty, state:
I/flutter ( 8842): _FutureBuilderState<String>#f9262):
I/flutter ( 8842): 'package:flutter/src/widgets/text.dart': Failed assertion: line 230 pos 15: 'data != null': is not
I/flutter ( 8842): true.
I am trying to build a list of the user's entitlements but I am not so sure as to how to deal with a null key such as "IP". The app works as long as the key has values inside but will return the exception if the key is null.
How should I deal with this problem?
IP is empty JsonObject
"IP": {},
So when you try to access data of IP object it returns null & passing that to textview later gives data is null error.
You are trying to get data from json object without keys as
var ip_ent = jsonEntDataIP["Entitlement"];
And using later as
new Text(ip_ent)
To overcome this you need to assign default value in case of variable is null or can hide that view as your requirement.
To assign default value in case of null, please do this.
var ip_ent = jsonEntDataIP["Entitlement"] ?? '';
var jsonEntDataIP = jsonEntData["IP"] ?? '';

Flutter: 'NoSuchMethodError' is not a subtype of type String

I currently have an app that pulls a list of providers through JSON.
This is the JSON file.
hospitals.json
{
"Johor": [
{
"Name": "KLINIK TAJ (MUAR)",
"TPA Customer ID": "1168",
"Organization Type": "Clinic",
"Organization Subtype": "GP",
"Street (Billing)": "35a, jalan abdullah ",
"City (Billing)": "muar",
"Postal Code (Billing)": "84000",
"State (Billing)": "Johor",
"Country (Billing)": "Malaysia",
"Coordinates": {
"Latitude": "2.041875",
"Longitude": "102.568235"
}
},
{
"Name": "KLINIK TAJ (PAGOH)",
"TPA Customer ID": "1169",
"Organization Type": "Clinic",
"Organization Subtype": "GP",
"Street (Billing)": "100 Main Road Pagoh",
"City (Billing)": "Muar",
"Postal Code (Billing)": "84600",
"State (Billing)": "Johor",
"Country (Billing)": "Malaysia",
"Coordinates": {
"Latitude": "2.148342",
"Longitude": "102.771002"
}
}
],
"Kedah": [
{
"Name": "KLINIK TAN",
"TPA Customer ID": "8423",
"Organization Type": "Clinic",
"Organization Subtype": "GP",
"Street (Billing)": "62 Jalan Raya",
"City (Billing)": "Kulim",
"Postal Code (Billing)": "9000",
"State (Billing)": "Kedah",
"Coordinates": {
"Latitude": "5.366739",
"Longitude": "100.553988"
}
},
{
"Name": "KLINIK SHAN",
"TPA Customer ID": "1685",
"Organization Type": "Clinic",
"Organization Subtype": "GP",
"Street (Billing)": "L. C. 19, Jalan Lunas,",
"City (Billing)": "Padang Serai",
"Postal Code (Billing)": "9000",
"State (Billing)": "Kedah",
"Coordinates": {
"Latitude": "5.402193",
"Longitude": "100.555209"
}
}
]
}
This is the model class of the JSON
new_accounts_model.dart
class Johor {
List<AccountInfo> accountinfo;
Johor({this.accountinfo});
factory Johor.fromJson(Map<String, dynamic> json){
var accJson = json["Johor"] as List;
List<AccountInfo> accList = accJson.map((i) => AccountInfo.fromJson(i)).toList();
return Johor(
accountinfo: accList
);
}
}
class AccountInfo{
String name;
String id;
String orgtype;
String subtype;
String street;
String city;
String country;
Coordinates coordinates;
AccountInfo({this.name, this.id, this.orgtype, this.subtype, this.street, this.city, this.country, this.coordinates});
factory AccountInfo.fromJson(Map<String, dynamic> json){
return AccountInfo(
name: json["Name"],
id: json["TPA Customer ID"],
orgtype: json["Organization Type"],
subtype: json["Organization Subtype"],
street: json["Street (Billing)"],
city: json["City (Billing)"],
country: json["State (Billing)"],
coordinates: Coordinates.fromJson(json["Coordinate"])
);
}
}
class Coordinates{
String lat;
String lng;
Coordinates({this.lat, this.lng});
factory Coordinates.fromJson(Map<String, dynamic> json){
return Coordinates(
lat: json["Latitude"],
lng: json["Longitude"]
);
}
}
And this is the dart file used to bring out the JSON file.
list.dart
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
import 'dart:convert';
import 'package:emas_app/model/new_accounts_model.dart';
Future<String> _loadAsset() async{
return await rootBundle.loadString('Assets/hospitals.json');
}
//Not working future
Future<Johor> loadJohor() async{
final response = await _loadAsset();
final jsonResponse = json.decode(response);
Johor johor = new Johor.fromJson(jsonResponse);
return johor;
}
class ProviderList extends StatefulWidget {
#override
ListState createState() {
return new ListState();
}
}
class ListState extends State<ProviderList> {
#override
Widget build(BuildContext context) {
List<Widget> widgets = [];
launchMapUrl(String lat, String lng) async{
String geoUri = "https://maps.google.com/maps?q=loc:$lat,$lng";
if (await canLaunch(geoUri)) {
print("Can launch");
await launch(geoUri);
} else {
print("Could not launch");
throw 'Could not launch Maps';
}
}
//method to bring out dialog
makeDialog(String address){
showDialog(
context: context,
builder: (_) => new SimpleDialog(
contentPadding: EdgeInsets.only(left: 30.0, top: 30.0),
children: <Widget>[
new Text("Address: $address",
style: TextStyle(
fontWeight: FontWeight.bold
),
),
new ButtonBar(
children: <Widget>[
new IconButton(
icon: Icon(Icons.close),
onPressed: (){
Navigator.pop(context);
}
)
],
)
],
)
);
}
widgets.add(new ExpansionTile(
title: new Text("Not working state"),
children: <Widget>[
new FutureBuilder<Johor>(
future: loadJohor(),
builder: (context, snapshot){
if(snapshot.hasData){
return new ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.accountinfo.length,
itemBuilder: (context, index){
String username = snapshot.data.accountinfo[index].name;
String address = snapshot.data.accountinfo[index].street;
String lat = snapshot.data.accountinfo[index].coordinates.lat;
String lng = snapshot.data.accountinfo[index].coordinates.lng;
return new ListTile(
title: new Text(username),
trailing: new Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new IconButton(
icon: Icon(Icons.info),
onPressed: (){
makeDialog(address);
}
),
new IconButton(
icon: Icon(Icons.directions),
onPressed: (){
launchMapUrl(lat, lng);
}
)
],
)
);
});
}else if(snapshot.hasError){
return new Center(
child: new Text(snapshot.error),
);
}
})
]
));
//empty list
widgets.add(new ExpansionTile(
title: new Text("Pahang")));
return new Scaffold(
appBar: new AppBar(title: new Text("Providers")),
body: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: widgets,
)
);
}
}
This is the error currently faced:
As the title says, the error is saying its a NoSuchMethodError. Therefore I am unsure as to what is causing this error in the first place.
My current guess is that I am not doing the Model class correctly but it could be something else.
I could really use some help in this case.
You are using wrong key for Coordinates.
You should use Coordinates as its name of key in json. But you are using Coordinate in method factory AccountInfo.fromJson
Update your last line of that method
coordinates: Coordinates.fromJson(json["Coordinates"])

Resources