Currenly using a .dart like this
const aList = <Map<String, dynamic>>[
{"url_helper": "aListFolder", "name": "a2a"},
{"url_helper": "aListFolder", "name": "a2b"},
];
const bList = <Map<String, dynamic>>[
{"url_helper": "bListFolder", "name": "b2a"},
{"url_helper": "bListFolder", "name": "b2b"},
];
const cList = <Map<String, dynamic>>[
{"url_helper": "cListFolder", "name": "c2a"},
{"url_helper": "cListFolder", "name": "c2b"},
];
const abList = [...aList, ..bList];
const allList = [...aList, ...bList, ...cList];
So I was using it in this way.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const UserPicked(
userchoise: abList, // user picked a and b list.
)),
);
Now, I put all the data in a .json
So it looks like this.
{
"aList" : [
{"url_helper": "aListFolder", "name": "a2a"},
{"url_helper": "aListFolder", "name": "a2b"}
],
"bList" : [
{"url_helper": "bListFolder", "name": "b2a"},
{"url_helper": "bListFolder", "name": "b2b"}
],
"cList" : [
{"url_helper": "cListFolder", "name": "c2a"},
{"url_helper": "cListFolder", "name": "c2b"}
],
}
How do I do the samething but with .json?
Future readJson() async {
final String response = await rootBundle.loadString('assets/json.json');
final data = await json.decode(response);
}
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const UserPicked(
userchoise: data['aList'], // user picked a list.
)),
);
Is it possible to do something like this, or should I still keep the same way using the .dart ?
Thanks for any help!
Don't forget to return your data, it's always good to declare a return type if you know what you want to return from there. This will make Flutter tell you the error.
Future<Map<String, dynamic>> readJson() async {
final String response = await rootBundle.loadString('assets/json.json');
final data = await json.decode(response);
return data;
}
Working with statically typed values is always easier than dynamic types.
Thats one of the reason why using the "dart" approach as you put it is better.
If you have some JSON data to work with ill recommend to convert it to dart data types first by making a fromMap function.
This is an example of how I do it:
class Roles {
final String? id;
final String name;
Roles({this.id, required this.name});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
};
}
factory Roles.fromMap(Map<String, dynamic> map) {
return Roles(
id: map['id'] != null ? map['id'] : null,
name: map['name'],
);
}
String toJson() => json.encode(toMap());
factory Roles.fromJson(String source) => Roles.fromMap(json.decode(source));
}
If this is what you are looking for please mark my answer as correct.
Related
This question already has answers here:
Flutter: filter list as per some condition
(4 answers)
Closed 5 days ago.
Response from API:
"loan": [
{
"id": "612",
"icbsid": "55",
"loanId": "null",
"loanAcctNo": "001-063-06881-1",
"productId": "4",
"productName": "Fixed Principal+Int(Adv Pym)",
"approvedDate": "2017-11-13",
"loanAmount": "7359.97",
"loanBalance": "0.0",
"monthsToPay": "36",
"interestRate": "12.0",
"dueDate": "2020-12-13",
"status": "Closed",
"lastPayment": "2020-01-10"
},
{
"id": "4970",
"icbsid": "55",
"loanId": "16",
"loanAcctNo": "001-263-01625-4",
"productId": "6",
"productName": "Regular Long Term",
"approvedDate": "2022-01-27",
"loanAmount": "9934.21",
"loanBalance": "5384.21",
"monthsToPay": "60",
"interestRate": "0.0",
"dueDate": "2027-08-25",
"status": "Disbursed",
"lastPayment": "2022-12-29"
}
]
This is my code and it's working fine, but I need to filter the status
` #override
Future<List?> fetchLoanList() async {
final response = await httpServices.getRequest('mobileAppGetIcbsid?icbsid=001-0000055');
final jsonData = json.decode(response.data);
var map = Map<String, dynamic>.from(jsonData);
var userData = UserModel.fromJson(map);
// userData.loan?.where((element) => element.status == "Closed"); <-- not working for me
return userData.loan;
}`
I tried to uncomment this code userData.loan?.where((element) => element.status == "Closed"); it is working fine for displaying the data but not filtering the status. I am expecting to display only the data where status == 'Closed'
.where will create a new modified list but not modify the original list. Either reassign the original list or return the modified list. In this case I think 2 is better because we are only doing one filter operation to the list.
Also, .where will return Iterable which is the superclass of List. As your function is returning a List, we have to use .toList() to convert the Iterable to List.
Reassign the original list
final response = await httpServices.getRequest('mobileAppGetIcbsid?icbsid=001-0000055');
final jsonData = json.decode(response.data);
var map = Map<String, dynamic>.from(jsonData);
var userData = UserModel.fromJson(map);
// Reassign the result of .where to modifiedUserData
var modifiedUserData = userData.loan?.where((element) => element.status == "Closed");
return modifiedUserList.toList();
Return the modified list
final response = await httpServices.getRequest('mobileAppGetIcbsid?icbsid=001-0000055');
final jsonData = json.decode(response.data);
var map = Map<String, dynamic>.from(jsonData);
var userData = UserModel.fromJson(map);
// Return the result of .where directly
return userData.loan?.where((element) => element.status == "Closed").toList();
void test() {
var json =
'{"loan":[{"id":"1", "icbsid": "55","loanId": "null", "status": "Closed"},{"id":"2", "icbsid": "55","loanId": "null", "status": "None"},{"id":"3", "icbsid": "25","loanId": "sss", "status": "None"} ]}';
final jsonData = jsonDecode(json);
var map = Map<String, dynamic>.from(jsonData);
var data = UserModel.fromJson(map);
data.loan?.removeWhere((model) => model.status != 'Closed');
data.loan?.forEach((model) {
pr('id::${model.id} status::${model.status}');
});
}
class UserModel {
List<Loan>? loan;
UserModel(this.loan);
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
(json['loan'] as List<dynamic>?)?.map((e) => Loan.fromJson(e)).toList());
}
class Loan {
String? id;
String? status;
Loan(this.id, this.status);
factory Loan.fromJson(Map<String, dynamic> json) =>
Loan(json['id'], json['status']);
}
When I start the project I got an unexpected null value.
I keep getting this error with this API, I don't have certain of what can be.
you can check here
api link: https://ffxivcollect.com/api/mounts/257
response
{
"id": 257,
"name": "Island Eggplant Knight",
"description": "Summon forth your island Eggplant Knight, an oversized vegetable embodiment of chivalry.",
"enhanced_description": "Hailing from the selfsame land as the Tomato King, the Eggplant Knight shared a crate with the sovereign when they were shipped out. However, he fell overboard when the vessel encountered rough seas, and drifted for days before being deposited on a desert island. Among other feats, he prides himself on having played a key role in the founding of the West Mandra Empire.",
"tooltip": "I thought ye were a feral turnip, a murderous eggplant, or summat like that! - Tiny Trader",
"movement": "Terrestrial",
"seats": 1,
"order": 240,
"order_group": 99,
"patch": "6.2",
"item_id": null,
"tradeable": false,
"owned": "3.9%",
"image": "https://ffxivcollect.com/images/mounts/large/257.png",
"icon": "https://ffxivcollect.com/images/mounts/small/257.png",
"bgm": "https://ffxivcollect.com/music/BGM_Ride_MJI.ogg",
"sources": [
{
"type": "Purchase",
"text": "12,000 Seafarer's Cowries",
"related_type": null,
"related_id": null
}
]
}
I'm using quick type to convert the JSON to dart and paste in the model only adding Required.
my home page:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(''),
),
body: ListView.builder(
itemCount: finalApi!.length,
itemBuilder: (context, index) {
return Container(
child: Text(finalApi![index].description),
);
},
),
);
}
}
url:
class RemoteService {
Future<List<FinalApi>> getPosts() async {
var client = http.Client();
var uri = Uri.parse('https://ffxivcollect.com/api/mounts/257');
var response = await client.get(uri);
if (response.statusCode == 200) {
var json = response.body;
return finalApiFromJson(json);
}
throw Text('aa');
}
}
my model:
List<FinalApi> finalApiFromJson(String str) =>
List<FinalApi>.from(json.decode(str).map((x) => FinalApi.fromJson(x)));
String finalApiToJson(List<FinalApi> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class FinalApi {
FinalApi({
required this.id,
required this.name,
required this.description,
required this.enhancedDescription,
required this.tooltip,
required this.movement,
required this.seats,
required this.order,
required this.orderGroup,
required this.patch,
required this.itemId,
required this.tradeable,
required this.owned,
required this.image,
required this.icon,
required this.bgm,
required this.sources,
});
int id;
String name;
String description;
String enhancedDescription;
String tooltip;
String movement;
int seats;
int order;
int orderGroup;
String patch;
dynamic itemId;
bool tradeable;
String owned;
String image;
String icon;
String bgm;
List<Source> sources;
factory FinalApi.fromJson(Map<String, dynamic> json) => FinalApi(
id: json["id"],
name: json["name"],
description: json["description"],
enhancedDescription: json["enhanced_description"],
tooltip: json["tooltip"],
movement: json["movement"],
seats: json["seats"],
order: json["order"],
orderGroup: json["order_group"],
patch: json["patch"],
itemId: json["item_id"],
tradeable: json["tradeable"],
owned: json["owned"],
image: json["image"],
icon: json["icon"],
bgm: json["bgm"],
sources:
List<Source>.from(json["sources"].map((x) => Source.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"description": description,
"enhanced_description": enhancedDescription,
"tooltip": tooltip,
"movement": movement,
"seats": seats,
"order": order,
"order_group": orderGroup,
"patch": patch,
"item_id": itemId,
"tradeable": tradeable,
"owned": owned,
"image": image,
"icon": icon,
"bgm": bgm,
"sources": List<dynamic>.from(sources.map((x) => x.toJson())),
};
}
class Source {
Source({
required this.type,
required this.text,
required this.relatedType,
required this.relatedId,
});
String type;
String text;
dynamic relatedType;
dynamic relatedId;
factory Source.fromJson(Map<String, dynamic> json) => Source(
type: json["type"],
text: json["text"],
relatedType: json["related_type"],
relatedId: json["related_id"],
);
Map<String, dynamic> toJson() => {
"type": type,
"text": text,
"related_type": relatedType,
"related_id": relatedId,
};
}
Based on your response, It is returning a single item on map. Therefor the parser will be like
final data = FinalApi.fromJson(jsonDecode(json));
class RemoteService {
Future<List<FinalApi>> getPosts() async {
var client = http.Client();
var uri = Uri.parse('https://ffxivcollect.com/api/mounts/257');
var response = await client.get(uri);
try {
if (response.statusCode == 200) {
var json = response.body;
// finalApiFromJson(json);
final data = FinalApi.fromJson(jsonDecode(json));
return [data];
}
} catch (e) {
log(e.toString());
}
return [];
}
}
I am an absolute beginner and would appreciate your help very much.
My json is as follows:
[
{
"id": "hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.humidity",
"val": 73,
"ts": 1661671736783,
"ack": true
},
{
"id": "hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.temperature",
"val": 16.8,
"ts": 1661671736782,
"ack": true
},
{
"id": "hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.weatherCondition",
"val": "CLEAR",
"ts": 1661671736783,
"ack": true
},
{
"id": "hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.weatherDayTime",
"val": "DAY",
"ts": 1661671736783,
"ack": true
},
{
"id": "hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.windDirection",
"val": 10,
"ts": 1661671736784,
"ack": true
},
{
"id": "hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.windSpeed",
"val": 18.503999999999998,
"ts": 1661671736784,
"ack": true
}
]
When I want to pick and show a particular value, e.g. for humidity, I get the following error:
type 'String' is not a subtype of 'int' of 'index'
My dart-code is as follows:
class EinzelwerteList {
final List<Wetter> einzelwerte;
EinzelwerteList({
required this.einzelwerte,
});
factory EinzelwerteList.fromJson(List<dynamic> parsedJson) {
List<Wetter> einzelwerte = <Wetter>[];
einzelwerte = parsedJson.map((i) => Wetter.fromJson(i)).toList();
return new EinzelwerteList(einzelwerte: einzelwerte);
}
}
class Wetter {
final String id;
final Int val;
final Int ts;
final Bool ack;
Wetter({
required this.id,
required this.val,
required this.ts,
required this.ack,
});
factory Wetter.fromJson(Map<String, dynamic> json) {
return Wetter(
id: json['id'].toString(),
val: json['val'],
ts: json['ts'],
ack: json['ack']);
}
}
Future<Wetter> fetchWetter() async {
final response = await http.get(Uri.parse(
'http://192.168.178.37:8087/getBulk/hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.humidity,hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.temperature,hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.weatherCondition,hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.weatherDayTime,hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.windDirection,hmip.0.homes.18c6789e-30e6-46c3-ba4b-1f94d284c178.weather.windSpeed'));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var dataDecoded = jsonDecode(response.body);
var humidity = dataDecoded['einzelwerte'][0]['val'].toString();
debugPrint(humidity);
return Wetter.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load Wetter');
}
}
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<Wetter> futureWetter;
#override
void initState() {
super.initState();
futureWetter = fetchWetter();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.green,
//scaffoldBackgroundColor:
),
home: Scaffold(
appBar: AppBar(
title: const Text('Micha lernt Flutter & Dart'),
),
body: Center(
child: FutureBuilder<Wetter>(
future: futureWetter,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.val.toString());
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return Container();
},
),
),
),
);
}
}
What do I do wrong?
As I said I am a total newbie and try to learn. So please be patient even if I ask dumb question.
Best regards.
There are multiple problems but the specific problem you are getting right now is the following piece of code:
var dataDecoded = jsonDecode(response.body);
var humidity = dataDecoded['einzelwerte'][0]['val'].toString();
The JSON does not contain a Map as the first level but instead a List. So you are getting an error since a List expects an int inside the [] while you are providing a String.
Another problem, you are going to have later, is that you are using the wrong types in your Wetter class. The types Int and Bool comes from dart:ffi and is meant to be used if you are integrating with native C code.
You should instead use int and bool.
A third problem is that val in your JSON contains a mix of types. So in your example you can see it is sometimes double and other times int and sometime String... the mix of int and double can be solved by use the num type but you need to add some custom handling for the String.
I have a JSON file and i want to fetch the data.
here a small Json example, in this Example as we see the employee has 2 properties,
name and List of countries :
{
"Employee": [
{
"id":1
"name": "John",
"Countries": [
{
"id" :1
"country": "Uk"
},
{
"id" :2
"country": "USA"
},
{
"id" :3
"country": "Germany"
}
]
}
]
}
I used to use this method to fetch the data from JSON but the problem i faced is that this method works just with Json that doesnt have a list property :
Future<List<EmployeeModel>> fetchEmployeeList() async {
try {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
var data = jsonDecode(response.body) as List;
print(data);
final employeeList = data.map((e) => EmployeeModel.fromJson(e)).toList();
return employeeList;
} else {
throw Exception("Failed to load ");
}
} catch (e) {
print(e);
rethrow;
}
}
here the model file :
import 'dart:convert';
List<EmployeeModel> employeeModelFromJson(String str) =>
List<EmployeeModel>.from(
json.decode(str).map((x) => EmployeeModel.fromJson(x)));
String employeeModelToJson(List<EmployeeModel> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class EmployeeModel {
EmployeeModel({
this.id,
this.name,
this.countries,
});
int id;
String name;
List<Country> countries;
factory EmployeeModel.fromJson(Map<String, dynamic> json) => EmployeeModel(
id: json["id"],
name: json["name"],
countries: List<Country>.from(
json["Countries"].map((x) => Country.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"Countries": List<dynamic>.from(countries.map((x) => x.toJson())),
};
}
class Country {
Country({
this.id,
this.country,
});
int id;
String country;
factory Country.fromJson(Map<String, dynamic> json) => Country(
id: json["id"],
country: json["country"],
);
Map<String, dynamic> toJson() => {
"id": id,
"country": country,
};
}
var data = jsonDecode(response.body);
print(data['Employee'][0]['Countries'][0]['country'];
//Output uk
Also consider creating a model for the json so you can parse it easily and don't have to write named keys.
https://docs.flutter.dev/development/data-and-backend/json
There are some online tools like quicktype.io too
EDIT
final employeeList = data.map((e) => EmployeeModel.fromJson(e)).toList();
print(employeeList[0].countries [0].country);
//Output uk
HERE IS THE JSON OF RESPONSE BODY:
{
"status": "success",
"contents": [{
"id": "15",
"cname": "DOGS",
"dogs_image": "1638695967-rtyyyt.jpg",
"cat_image": "1638695967-jhjjj.jpg",
"sub_category": [{
"subcatid": "36",
"cat_id": "15",
"sub_category_name": "Accessories",
"banner": null,
"image": "1638695982-ACCESORIE.jpg"
}, {
"subcatid": "39",
"cat_id": "15",
"sub_category_name": "Beds",
"banner": null,
"image": "1638695982-ACCESORIE.jpg"
}]
}, {
"id": "14",
"cname": "CATS",
"dogs_image": "1638695967-rtyyyt.jpg",
"cat_image": "1638695967-jhjjj.jpg",
"sub_category": [{
"subcatid": "47",
"cat_id": "14",
"sub_category_name": "Accessories",
"banner": null,
"image": "1638695982-ACCESORIE.jpg"
}]
}]
}
// API call to get the above json data:
Future<List<CatListData>> dashboardDataAPI(http.Client client) async {
final response = await client.get(Uri.parse(Utilities.BASE_URL));
List list = json.decode(response.body)['contents'];
return parsePhotos(list.toString());
}
// A function that converts a response body into a List
List<CatListData> parsePhotos(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<CatListData>((json) => CatListData.fromJson(json)).toList();
}
// Cat List Class
class CatListData{
final String id;
final String cName;
final String dogImage;
final String catImage;
final List<SubCatListData> subCatListDataList;
CatListData({required this.id, required this.cName, required this.dogImage, required this.catImage, required this.subCatListDataList});
factory CatListData.fromJson(Map<String, dynamic> json) {
return CatListData(
id: json['id'] as String,
cName: json['cname'] as String,
dogImage: json['dogs_image'] as String,
catImage: json['cat_image'] as String,
subCatListDataList: List<SubCatListData>.from(json['sub_category'] as Iterable),
);
}
}
// Sub Cat Class
class SubCatListData{
final String subCatId;
final String catId;
final String subCategoryName;
final String banner;
final String image;
SubCatListData({required this.subCatId, required this.catId, required this.subCategoryName, required this.banner, required this.image});
factory SubCatListData.fromJson(Map<String, dynamic> json) {
return SubCatListData(
subCatId: json['subcatid'] as String,
catId: json['cat_id'] as String,
subCategoryName: json['sub_category_name'] as String,
banner: json['banner'] as String,
image: json['image'] as String,
);
}
}
Here showing null when I print snapshot
Container(
child: FutureBuilder<List<CatListData>>(
future: dashboardDataAPI(http.Client()),
builder: (context, snapshot) {
print("Response:: "+snapshot.data.toString());
if (snapshot.hasData) {
return PhotosList(photos: snapshot.data!);
}else if(snapshot.hasError){
return const Center(
child: Text('An error has occurred!'),);
}else{
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
)
Please let me know how I can fix this issue and parse the multiple json array data into the list.
Thanks
I believe the problem happens on this line on the CatListData.fromJson constructor:
subCatListDataList: List<SubCatListData>.from(json['sub_category'] as Iterable),
you never call SubCatListData.fromJson, I believe this will work better for your assignment:
subCatListDataList: (json['sub_category'] as Iterable).map<SubCatListData>(
(value) => SubCatListData.fromJson(value as Map<String, dynamic>),
),