How to get values from API with dynamic dates? Dart/Flutter - json

I have an issue with fetching data from API, my goal is to get separated data like only dates and only values of currency. Basically at some point in trying to solve this problem I've got dates as keys but couldn't get the values of currency. Now I'm getting only nulls.
The response is:
{
"base": "EUR",
"end_date": "2020-06-06",
"rates": {
"2020-06-01": {
"USD": 1.112558
},
"2020-06-02": {
"USD": 1.118756
},
"2020-06-03": {
"USD": 1.123471
},
"2020-06-04": {
"USD": 1.133657
},
"2020-06-05": {
"USD": 1.129095
},
"2020-06-06": {
"USD": 1.12915
}
},
"start_date": "2020-06-01",
"success": true,
"timeseries": true
}
This is what I use to retrieve that data. But I don't know how to properly go through the random dates
import 'dart:convert';
import 'package:currency_exchange/models/currency.dart';
import 'package:currency_exchange/models/rate_timeseries.dart';
class CurrencyTimeseries {
CurrencyTimeseries({
required this.base,
required this.endDate,
required this.rates,
required this.startDate,
required this.success,
required this.timeseries,
});
Currency base;
DateTime endDate;
Rate rates;
DateTime startDate;
bool success;
bool timeseries;
factory CurrencyTimeseries.fromJson(
Map<String, dynamic> json, Currency symbol) =>
CurrencyTimeseries(
base: Currency.values
.firstWhere((element) => element.name == json['base']),
endDate: DateTime.parse(json["end_date"]),
rates: Rate.fromJson(json["rates"]),
success: json["success"] == "true",
startDate: DateTime.parse(json["start_date"]),
timeseries: json["timeseries"],
);
}
Here is class Rate used for this code above
import 'dart:convert';
class Rate {
Rate({
required this.eur,
});
double eur;
factory Rate.fromJson(Map<String, dynamic> json) => Rate(
eur: json["EUR"],
);
}
The last one is here, how I send req to API, and its working
Future<CurrencyTimeseries> fetchTimeseries(
Currency base,
DateTime endDate,
DateTime startDate,
Currency symbol,
) async {
RequestOptions req = RequestOptions(
path: '/timeseries',
queryParameters: {
'base': base.name,
'end_date': DateFormat('yyyy-MM-dd').format(endDate),
'start_date': DateFormat('yyyy-MM-dd').format(startDate),
'symbols': symbol.name,
},
baseUrl: _apiUrl,
headers: {'apikey': _apiKey},
method: 'GET',
);
Response response = await _dio.fetch(req);
print(response.data);
return CurrencyTimeseries.fromJson(
response.data,
symbol,
);
}

This is how to access rates:
final startDate = json["start_date"];
final endDate = json["end_date"];
final startDateUSD = json["rates"][startDate]["USD"];
...
final endDateUSD = json["rates"][endDate]["USD"];

Related

Error To show Data Parsed Json In Flutter

I Have One Http Post Method Like This :
class ApiClientController extends GetxController {
Future<GetSideMenuInfoError?> GetInfoAfterLogin() async {
String? value = await storage.read(key: 'skey');
try {
final response = await dio.post(
Constant.baseUrl,
options: Options(
headers: {
"omax-apikey": "apikey",
},
),
data: {
"function": "portal_get_information",
"params": {
"portal_version": "1.0.0",
"portal_os": "linux",
"portal_os_version": "10",
"portal_browser": "chrome",
"portal_guid": "fd298776-6014-11ed-adbc-5256454165"
}
},
);
//print(response.data.toString());
GetSideMenuInfoError? responseBody = getSideMenuInfoErrorFromJson(response.data.toString());
return responseBody;
} on DioError catch (e) {
//return ;
print(e);
}
return null;
//IMPLEMENT USER LOGIN
}
}
And The Result Post Method My Json :
{
"result": 55456465,
"data": {
"reason": "session expired or not valid",
"uuid": "01dfca14-625559-11ed-aafa-0056546546"
}
}
Used This https://app.quicktype.io/ for Parsed Json To dart File Result Like This:
import 'package:meta/meta.dart';
import 'dart:convert';
GetSideMenuInfoError? getSideMenuInfoErrorFromJson(String str) => GetSideMenuInfoError?.fromJson(json.decode(str));
class GetSideMenuInfoError {
GetSideMenuInfoError({
#required this.result,
#required this.data,
});
final int? result;
final Data? data;
factory GetSideMenuInfoError.fromJson(Map<String, dynamic> json) => GetSideMenuInfoError(
result: json["result"],
data: Data.fromJson(json["data"]),
);
}
class Data {
Data({
#required this.reason,
#required this.uuid,
});
final String? reason;
final String? uuid;
factory Data.fromJson(Map<String, dynamic> json) => Data(
reason: json["reason"],
uuid: json["uuid"],
);
}
And My Question Is : How Can I Show value in Dart File Like reason or uuid In Other Class ?
My Way like This in Other Class And Not Worked:
In The Build Widget :
final apiClientController = Get.find<ApiClientController>();
apiClientController.GetInfoAfterLogin();
GetSideMenuInfoError? getSideMenuInfoError;
title: getSideMenuInfoError != null ?
Text(getSideMenuInfoError.result.toString()):Text('',),
Thank You For Helping Me...

Json got parsed but the cannot display the data in the UI flutter

I was trying to fetch data results from a REST API and then display it in the UI. So everything went well the JSON was parsed well the try and catch method was working fine. But somehow the code was not able to display the parsed results in the UI. Neither gave me an error or exception. I have been struggling to attain the desired result for quite the past few days.
Model Class:
import 'dart:convert';
Transaction transactionFromJson(String str) =>
Transaction.fromJson(json.decode(str));
String transactionToJson(Transaction data) => json.encode(data.toJson());
class Transaction {
Transaction({
required this.dataDescription,
required this.orderStatus,
required this.statusObjects,
});
String dataDescription;
String orderStatus;
List<StatusObject> statusObjects;
factory Transaction.fromJson(Map<String, dynamic> json) => Transaction(
dataDescription: json["data-description"],
orderStatus: json["order-status"],
statusObjects: List<StatusObject>.from(
json["status-objects"].map((x) => StatusObject.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"data-description": dataDescription,
"order-status": orderStatus,
"status-objects":
List<dynamic>.from(statusObjects.map((x) => x.toJson())),
};
}
class StatusObject {
StatusObject({
required this.type,
required this.status,
required this.date,
required this.time,
});
String type;
String status;
DateTime date;
String time;
factory StatusObject.fromJson(Map<String, dynamic> json) => StatusObject(
type: json["type"],
status: json["status"],
date: DateTime.parse(json["date"]),
time: json["time"],
);
Map<String, dynamic> toJson() => {
"type": type,
"status": status,
"date": date.toIso8601String(),
"time": time,
};
}
This is how the JSON looks like:
{
"data-description": "This api will return an array of objects to be placed in the order status timeline on the second screen",
"order-status": "Success",
"status-objects": [
{
"type": "Payment",
"status": "completed",
"date": "2021-07-02T00:00:00",
"time": "12:00AM"
},
{
"type": "Units Allocated",
"status": "by Axis",
"date": "2021-07-13T00:00:00",
"time": "12:00AM"
}
]
}
API_Manager where the parsing and fetching took place Service Class
class API_Manager {
static Future<Transaction> getDetails() async {
var client = http.Client();
var transactions;
try {
var response = await client.get(
Uri.https("your api url here"));
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = jsonDecode(jsonString);
transactions = Transaction.fromJson(jsonMap);
}
} catch (e) {
return transactions;
}
return transactions;
}
}
The UI component where I wanted to display the parsed JSON:
Code
FutureBuilder<Transaction>(
future: API_Manager.getDetails(),
builder: (context, snapshot) {
if (snapshot.hasData) {
var data = snapshot.data!.statusObjects;
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) =>
Text('$index : ${data[index].status}'),
);
}
return Text('Something was wrong!');
},
),
The output that I am getting is "Something was wrong"
I am quite sure that I have been missing a very small piece of code to make it work. I have been working on this piece of code for quite a few days but am unable to do it. I request you, people, to please help me out in attaining the result or point out the piece of code that I have left out.
Will appreciate it if you could help me in any possible way.
try this
var response = await client
.get(Uri.https("domain", "accounts/test-data/"));
or
var response = await http
.get(Uri.parse("domain/accounts/test-data/"));
This one doesn't work maybe because of the main domain part shouldn't use /, because it indicates subPath,
var response = await client
.get(Uri.https("domain/accounts", "test-data/"));

Flutter : How to parse JSON Array of objects

Can anyone tell me how to parse arrays of object in flutter. When I am parsing the json I am getting error as List is not a subtype of type Map<String, dynamic>.
Below is my json file which needs to be parsed. Please help me to fix this issue.
[
{
"empPayslipsId": "2021012000440",
"month": "Jan",
"description": "Payslip for JAN 2021 (Month End)",
"paymentPeriod": "1/1/2021 12:00:00 AM - 1/31/2021 12:00:00 AM",
"lastAccessBy": "0002\r\n118.200.199.70",
"lastAccessDate": "20210202",
"lastAccessTime": "105706",
"successAccess": "2",
"failAccess": "2"
}
]
Future<void> loadQueryPeriod(int year, var month) async {
String baseURL = '${domainURL}api/PaySlip?year=$year&month=$month';
try {
final response = await http.get(baseURL, headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization':
'Bearer ${Provider.of<UserVM>(navigatorKey.currentContext, listen: false).accessToken}',
});
print('UIC PDF response : ${response.body}');
print(
'UIC Token response : ${Provider.of<UserVM>(navigatorKey.currentContext, listen: false).accessToken}');
if (response.statusCode == 200) {
final Map<String, dynamic> data = json.decode(response.body);
print('result type: ${data.runtimeType}');
}
} catch (e) {
print(e);
throw Exception('Download PDF Fail! ${e.toString()}');
}
}
}
Change it to this:
final Map<String, dynamic> data = json.decode(response.body)[0];
This is because your map is inside a list. Look at the square brackets [ ] enclosing your map. The map that you need, is at index[0] of this list.
use this podo class :
// Generated by https://quicktype.io
// To parse this JSON data, do
//
// final sample = sampleFromJson(jsonString);
import 'dart:convert';
List<Sample> sampleFromJson(String str) {
final jsonData = json.decode(str);
return new List<Sample>.from(jsonData.map((x) => Sample.fromJson(x)));
}
String sampleToJson(List<Sample> data) {
final dyn = new List<dynamic>.from(data.map((x) => x.toJson()));
return json.encode(dyn);
}
class Sample {
String empPayslipsId;
String month;
String description;
String paymentPeriod;
String lastAccessBy;
String lastAccessDate;
String lastAccessTime;
String successAccess;
String failAccess;
Sample({
this.empPayslipsId,
this.month,
this.description,
this.paymentPeriod,
this.lastAccessBy,
this.lastAccessDate,
this.lastAccessTime,
this.successAccess,
this.failAccess,
});
factory Sample.fromJson(Map<String, dynamic> json) => new Sample(
empPayslipsId: json["empPayslipsId"],
month: json["month"],
description: json["description"],
paymentPeriod: json["paymentPeriod"],
lastAccessBy: json["lastAccessBy"],
lastAccessDate: json["lastAccessDate"],
lastAccessTime: json["lastAccessTime"],
successAccess: json["successAccess"],
failAccess: json["failAccess"],
);
Map<String, dynamic> toJson() => {
"empPayslipsId": empPayslipsId,
"month": month,
"description": description,
"paymentPeriod": paymentPeriod,
"lastAccessBy": lastAccessBy,
"lastAccessDate": lastAccessDate,
"lastAccessTime": lastAccessTime,
"successAccess": successAccess,
"failAccess": failAccess,
};
}
Now inorder to parse json call,
Sample sample = sampleFromJson(jsonString);
via this you will get the access to sample PODO class and you can access any object you want.
The initial data you received by calling a get request isn't stored in a map, but rather in a list.
You should do something like this to receive your initial data.
if (response.statusCode == 200) {
final List<dynamic> data = json.decode(response.body);
}
From there, they're numerous ways to get the data from your data variable. You can use lists here if you want, for example to get the value of month in the JSON.
final String month = data[0]['month'];
If you'd prefer to use Maps, the syntax it'll look like this
final Map<String, dynamic> endpointData = data[0];
final String responseKey = 'month';
final var result = endpointData[responseKey];
if you have data model you can do it like this
fromJsonList(List<dynamic> jsonList) {
List<YourModel> yourModelList = [];
jsonList.forEach((jsonModel) {
menuModelsOfferList.add(YourModel.fromJson(jsonModel));
});

how to get data from json to a string in flutter

i am getting the json response from the url,i want to show the data in my screen design(i.e append the data to related fields),but i am getting the error as data is null
And here i am adding my controller
feacthstoredetailsdata() async {
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
final SharedPreferences prefs = await _prefs;
print("PRINT ====> " + prefs.getString("BearerToken"));
var receivedToken = "Bearer " + prefs.getString("BearerToken");
// var id=1;
var receivedstoreid=prefs.getString("store_id");
print("=========================="+receivedstoreid);
print("PRINT ::: receivedToken ====> " + receivedToken);
var res = await http.get("http://your domain.com/api/rest/stores/${receivedstoreid}",
headers: {
'Authorization': receivedToken
},
);
var decodedjson = jsonDecode(res.body);
storeDetails = StoreDetails.fromJson(decodedjson);
var res1 = storeDetails.toJson();
print(res1);
// return storeDetails;
setState(() {});
}
And i am try to append the data to screen as below
child: Container(
height: 250.0,
width: 250.0,
margin: EdgeInsets.all(5.0),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(storeDetails.data.thumb))),
),
),
),
here storeDetails is my model class name
{success: true, data: {store_id: 1, store_image: catalog/stores/asian_spice_market/asian_spice_market_logo.png, thumb: http://bagbash.com/image/cache/catalog/stores/asian_spice_market/asian_spice_market_logo-500x500.png, store_language: en-gb, store_comment: Shop for ¥6000 and get Free delivery., store_open: 10AM-10PM, store_fax: , store_telephone: 0804053636, store_email: kumar4675#i.softbank.jp, store_geocode: , store_address: Yokohama Shi, Naka ku, Noge cho 3-160-4, store_owner: Asian Spice Market, store_name: Asian Spice Market, store_url: http://asianspicemarket.bagbash.com/, longitude: , latitude: }}
this is the response i am getting
Based on your question, i can conclude one of two things could cause the error
1)Your api returns null.
2)Your json decoding system is broken somewhere.
To fix the first error you would have to check the code from the api .
To fix the second error you could use tools like this json to dart to generate model clasess or go in and manually edit your model, though tedious but most flexible.
Bonus in dart there is Null-aware Operators -> ??.
Instead of having the ui display null errors you could place a default placeholder wherever there is null.
json string you post can not use directly. here is what I modified.
{"success": true,
"data": {
"store_id": 1,
"store_image": "catalog/stores/asian_spice_market/asian_spice_market_logo.png",
"thumb": "http://bagbash.com/image/cache/catalog/stores/asian_spice_market/asian_spice_market_logo-500x500.png",
"store_language": "en-gb",
"store_comment": "Shop for ¥6000 and get Free delivery.",
"store_open": "10AM-10PM",
"store_fax": "",
"store_telephone": "0804053636",
"store_email": "kumar4675#i.softbank.jp",
"store_geocode": "",
"store_address": "Yokohama Shi, Naka ku, Noge cho 3-160-4",
"store_owner": "Asian Spice Market, store_name: Asian Spice Market",
"store_url": "http://asianspicemarket.bagbash.com/",
"longitude": "",
"latitude":""
}
}
you can parse with this
// To parse this JSON data, do
//
// final storeDetails = storeDetailsFromJson(jsonString);
import 'dart:convert';
StoreDetails storeDetailsFromJson(String str) => StoreDetails.fromJson(json.decode(str));
String storeDetailsToJson(StoreDetails data) => json.encode(data.toJson());
class StoreDetails {
bool success;
Data data;
StoreDetails({
this.success,
this.data,
});
factory StoreDetails.fromJson(Map<String, dynamic> json) => new StoreDetails(
success: json["success"],
data: Data.fromJson(json["data"]),
);
Map<String, dynamic> toJson() => {
"success": success,
"data": data.toJson(),
};
}
class Data {
int storeId;
String storeImage;
String thumb;
String storeLanguage;
String storeComment;
String storeOpen;
String storeFax;
String storeTelephone;
String storeEmail;
String storeGeocode;
String storeAddress;
String storeOwner;
String storeUrl;
String longitude;
String latitude;
Data({
this.storeId,
this.storeImage,
this.thumb,
this.storeLanguage,
this.storeComment,
this.storeOpen,
this.storeFax,
this.storeTelephone,
this.storeEmail,
this.storeGeocode,
this.storeAddress,
this.storeOwner,
this.storeUrl,
this.longitude,
this.latitude,
});
factory Data.fromJson(Map<String, dynamic> json) => new Data(
storeId: json["store_id"],
storeImage: json["store_image"],
thumb: json["thumb"],
storeLanguage: json["store_language"],
storeComment: json["store_comment"],
storeOpen: json["store_open"],
storeFax: json["store_fax"],
storeTelephone: json["store_telephone"],
storeEmail: json["store_email"],
storeGeocode: json["store_geocode"],
storeAddress: json["store_address"],
storeOwner: json["store_owner"],
storeUrl: json["store_url"],
longitude: json["longitude"],
latitude: json["latitude"],
);
Map<String, dynamic> toJson() => {
"store_id": storeId,
"store_image": storeImage,
"thumb": thumb,
"store_language": storeLanguage,
"store_comment": storeComment,
"store_open": storeOpen,
"store_fax": storeFax,
"store_telephone": storeTelephone,
"store_email": storeEmail,
"store_geocode": storeGeocode,
"store_address": storeAddress,
"store_owner": storeOwner,
"store_url": storeUrl,
"longitude": longitude,
"latitude": latitude,
};
}
Try changing this line of code from
image: NetworkImage(storeDetails.data.thumb))),
to
image: NetworkImage(decodedjson['data']['thumb']))),
If the above suggestion does not work as expected, you may have to consider what #chunhunghan has pointed out and re-format your JSON data. I had to painstakingly['manually'] reformat the JSON to end up with this:
{
"success": "true",
"data": {
"store_id": "1",
"store_image": "catalog/stores/asian_spice_market/asian_spice_market_logo.png",
"thumb": "http://bagbash.com/image/cache/catalog/stores/asian_spice_market/asian_spice_market_logo-500x500.png",
"store_language": "en-gb",
"store_comment": "Shop for ¥6000 and get Free delivery.",
"store_open": "10AM-10PM",
"store_fax": "",
"store_telephone": "0804053636",
"store_email": "kumar4675#i.softbank.jp",
"store_geocode": "",
"store_address": "Yokohama Shi, Naka ku, Noge cho 3-160-4",
"store_owner": "Asian Spice Market",
"store_name": "Asian Spice Market",
"store_url": "http://asianspicemarket.bagbash.com/",
"longitude": "",
"latitude": ""
}
}
JSON view using Awesome JSON

Parsing JSON that has a nested array of objects in Dart?

I am making a Flutter app and I am using The MovieDB api to get data. When I call the api and ask for a specific movie, this is the general format that I get back:
{
"adult": false,
"backdrop_path": "/wrqUiMXttHE4UBFMhLHlN601MZh.jpg",
"belongs_to_collection": null,
"budget": 120000000,
"genres": [
{
"id": 28,
"name": "Action"
},
{
"id": 12,
"name": "Adventure"
},
{
"id": 878,
"name": "Science Fiction"
}
],
"homepage": "http://www.rampagethemovie.com",
"id": 427641,
"imdb_id": "tt2231461",
"original_language": "en",
"original_title": "Rampage",
...
}
I have setup a model class for to parse this and the class is defined as such:
import 'dart:async';
class MovieDetail {
final String title;
final double rating;
final String posterArtUrl;
final backgroundArtUrl;
final List<Genre> genres;
final String overview;
final String tagline;
final int id;
const MovieDetail(
{this.title, this.rating, this.posterArtUrl, this.backgroundArtUrl, this.genres, this.overview, this.tagline, this.id});
MovieDetail.fromJson(Map jsonMap)
: title = jsonMap['title'],
rating = jsonMap['vote_average'].toDouble(),
posterArtUrl = "http://image.tmdb.org/t/p/w342" + jsonMap['backdrop_path'],
backgroundArtUrl = "http://image.tmdb.org/t/p/w500" + jsonMap['poster_path'],
genres = (jsonMap['genres']).map((i) => Genre.fromJson(i)).toList(),
overview = jsonMap['overview'],
tagline = jsonMap['tagline'],
id = jsonMap['id'];
}
class Genre {
final int id;
final String genre;
const Genre(this.id, this.genre);
Genre.fromJson(Map jsonMap)
: id = jsonMap['id'],
genre = jsonMap['name'];
}
My issue is that I can't get the genre to parse properly from the JSON. When I get the JSON and pass it through my model class, I get the following error:
I/flutter (10874): type 'List<dynamic>' is not a subtype of type 'List<Genre>' where
I/flutter (10874): List is from dart:core
I/flutter (10874): List is from dart:core
I/flutter (10874): Genre is from package:flutter_app_first/models/movieDetail.dart
I thought this would work because I have made a different class for the Genre object and passed in the JSON array as a list. I don't understand how List<dynamic> isn't a child of List<Genre> because doesn't the keyword dynamic imply any object? Does anyone know how to parse a nested JSON array into custom objects?
Try genres = (jsonMap['genres'] as List).map((i) => Genre.fromJson(i)).toList()
The issue: calling map without the cast makes it a dynamic call, which means the return type from Genre.fromJson is also dynamic (not Genre).
Take a look at https://flutter.io/json/ for some hints.
There are solutions, like https://pub.dartlang.org/packages/json_serializable, that makes this much easier
I think JSONtoDart Converter is very useful, Must try...
After receiving the response, first of all, you need to extract the arrays separately. Then you can easily map. This is the way I do it.
List<Attempts> attempts;
attempts=(jsonDecode(res.body)['message1'] as List).map((i) => Attempts.fromJson(i)).toList();
List<Posts> posts;
attempts=(jsonDecode(res.body)['message2'] as List).map((i) => Post.fromJson(i)).toList();
Refer below example.
Future<List<Attempts>> getStatisticData() async {
String uri = global.serverDNS + "PaperAttemptsManager.php";
var res = await http.post(
uri,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'userName': widget.userId,
'subject': widget.subjectName,
'method': "GETPTEN",
}),
);
if (res.statusCode == 200) {
List<Attempts> attempts;
attempts=(jsonDecode(res.body)['message'] as List).map((i) => Attempts.fromJson(i)).toList();
return attempts;
} else {
throw "Can't get subjects.";
}
}
Model Class
class Attempts {
String message, userName, date, year, time;
int status, id, marks, correctAnswers, wrongAnswers, emptyAnswers;
Attempts({
this.status,
this.message,
this.id,
this.userName,
this.date,
this.year,
this.marks,
this.time,
this.correctAnswers,
this.wrongAnswers,
this.emptyAnswers,
});
factory Attempts.fromJson(Map<String, dynamic> json) {
return Attempts(
status: json['status'],
message: json['message'],
id: json['ID'],
userName: json['USERNAME'],
date: json['DATE'],
year: json['YEAR'],
marks: json['MARKS'],
time: json['TIME'],
correctAnswers: json['CORRECT_ANSWERS'],
wrongAnswers: json['WRONG_ANSWERS'],
emptyAnswers: json['EMPTY_ANSWERS'],
);
}
}