Dart - Convert Map of objects fetched via HTTP REST-API - flutter

For my Calendar i get the following data as JSON from the Backend (*JAVA-Type = Map<LocalDate, List<Event>>):
{
"2022-05-28": [
{
"id": 2,
"title": "Multi day Event",
"fromDate": "2022-05-27T12:22:03.873569",
"toDate": "2022-05-28T11:22:03.873569",
"room": {
"id": 1,
"name": "TestRoom",
},
"user": {
"id": 1,
"name": "Andi",
"city": "",
"email": "test#gmail.com",
},
"eventType": "sozial"
}
],
"2022-05-27": [
{
"id": 2,
"title": "Multi day Event",
"fromDate": "2022-05-27T12:22:03.873569",
"toDate": "2022-05-28T11:22:03.873569",
"room": {
"id": 1,
"name": "TestRoom",
},
"user": {
"id": 1,
"name": "Andi",
"city": "",
"email": "test#gmail.com",
},
"eventType": "sozial"
},
{
"id": 1,
"title": "Testevent",
"fromDate": "2022-05-27T11:21:04.573754",
"toDate": "2022-05-27T12:21:04.573754",
"room": {
"id": 1,
"name": "TestRoom",
},
"user": {
"id": 1,
"name": "Andi",
"city": "",
"email": "test#gmail.com",
},
"eventType": "normal"
}
],
}
My Event Class looks like:
Class Event {
int id;
String title;
DateTime fromDate;
DateTime toDate;
Room room;
User user;
String eventType;
}
Now i need the same structure i had in the Backend (Map<DateTime, <List<Event>>) for my Calendar widget and i have no real clue on how to do it. I know how to convert json data into an object if i get a list of an object, but how can i store the date as key of the resulting map?
My code by now:
Future<Map<DateTime, List<Event>>> getEvents(DateTime _fromDate, DateTime
_endDate) async {
String _from = _fromDate.toString().split('.').first;
String _end = _endDate.toString().split('.').first;
final response = await get('${_url}calendar/events/$_from/$_end',
headers: {HttpHeaders.authorizationHeader: 'Bearer $_bearer'});
if (response.status.hasError) {
return Future.error('${response.statusText}');
} else {
final parsed = jsonDecode(response.body);
return parsed;
}
}

You need to do something like that:
var json = {...}; // <-- json obj
// method to parse data to map with list Event
dynamic fromJson(Map<String, dynamic> json){
var map = new Map();
json.keys.forEach((key){
// key is the date
map[key] = json[key].map((e) => Event.fromJson(e)).toList(); // <- need to create a method fromJson in your Event class
});
return map;
}
(...)
class Event {
int id;
String title;
DateTime fromDate;
DateTime toDate;
Room room;
User user;
String eventType;
fromJson(Map<String, dynamic> json) => Event(...); // <- parse json to Event class
}

Related

Flutter API Call using http

I'm trying to get json data from Api by using the following
Future<SubjectList> getsubjectList(
String userId, String accountId) async {
final response = await http
.get(Uri.https(_baseUrl, 'v1/package/subject-details'), headers: {
'Content-Type': 'application/json',
'user-id': userId,
'account-id': accountId,
});
SubjectList jsonresponse = json.decode(response.body); //'_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'SubjectList'
print('This is response =$jsonresponse');
return jsonresponse;
}
I have modelled the object as follows
class SubjectList {
SubjectList({
this.subject,
this.score,
this.progress,
});
String? subject;
double? score;
String? progress;
factory SubjectList.fromMap(Map<String, dynamic> json) => SubjectList(
subject: json["subject"],
score: json["score"].toDouble(),
progress: json["progress"],
);
Map<String, dynamic> toJson() => {
"subject": subject,
"score": score,
"progress": progress,
};
}
The Data is as follows
{
"success": true,
"data": [
{
"subject": "Grammar",
"score": 57.17,
"progress": "96.77%"
},
{
"subject": "Maths",
"score": 52.12,
"progress": "73.08%"
},
{
"subject": "EVS",
"score": 55.75,
"progress": "97.96%"
},
{
"subject": "Social Studies",
"score": -1,
"progress": "-1%"
},
{
"subject": "Hindi",
"score": 51.36,
"progress": "60.87%"
},
{
"subject": "Vocabulary",
"score": 62.55,
"progress": "68.12%"
},
]
When ever i try to access using the model i'm receiving the error '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'SubjectList'. How do I get the data properly ?
Change this line
SubjectList jsonresponse = json.decode(response.body);
to something like
List<SubjectList> list = json.decode(response.body)['data'].map((d) => SubjectList.fromMap()).toList();
You can create a class for the response itself and the do the fromMap on it.

Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic> While working on a Todo App

I am trying to get data from a local API into my project, i am facing the following problem:
Unhandled Exception: type 'List' is not a subtype of type 'Map<String, dynamic>'
// To parse this JSON data, do
//
// final toDo = toDoFromJson(jsonString);
import 'dart:convert';
import 'package:http/http.dart' as http;
ToDo toDoFromJson(String str) => ToDo.fromJson(json.decode(str));
String toDoToJson(ToDo data) => json.encode(data.toJson());
class ToDo {
ToDo({
required this.id,
required this.img,
required this.name,
required this.title,
required this.done,
required this.note,
required this.priority,
required this.dueDate,
required this.taskOwner,
required this.studentId,
required this.createdAt,
required this.updatedAt,
});
int id;
String img;
String name;
String title;
int done;
String note;
String priority;
String dueDate;
int taskOwner;
String studentId;
String createdAt;
String updatedAt;
factory ToDo.fromJson(Map<String, dynamic> json) => ToDo(
id: json["id"],
img: json["img"],
name: json["name"],
title: json["title"],
done: json["done"],
note: json["note"],
priority: json["priority"],
dueDate: json["due_date"],
taskOwner: json["TaskOwner"],
studentId: json["studentId"],
createdAt: json["createdAt"],
updatedAt: json["updatedAt"],
);
Map<String, dynamic> toJson() => {
"id": id,
"img": img,
"name": name,
"title": title,
"done": done,
"note": note,
"priority": priority,
"due_date": dueDate,
"TaskOwner": taskOwner,
"studentId": studentId,
"createdAt": createdAt,
"updatedAt": updatedAt,
};
}
Future<List<ToDo>> fetchTodos() async {
final response =
await http.get(Uri.parse('http://localhost:3000/task/all/1'));
if (response.statusCode == 200) {
final List<ToDo> todo = toDoFromJson(response.body) as List<ToDo>;
print(todo);
return todo;
} else {
print("nothing found");
return [];
}
}
Json from API is as below:
{
"id": 1,
"img": "assets/images/user/user1.jpg",
"name": "task 1",
"title": "eee",
"done": 0,
"note": "eee",
"priority": "Normal",
"due_date": "2021-07-06T18:30:00.000Z",
"TaskOwner": 1,
"studentId": "2",
"createdAt": "2021-07-26T14:39:54.000Z",
"updatedAt": "2021-07-26T14:39:54.000Z"
},
{
"id": 2,
"img": "assets/images/user/user1.jpg",
"name": "task 2",
"title": "nnjn",
"done": 0,
"note": "2525",
"priority": "High",
"due_date": "2021-07-19T18:30:00.000Z",
"TaskOwner": 1,
"studentId": "7",
"createdAt": "2021-07-27T15:05:31.000Z",
"updatedAt": "2021-07-27T15:05:31.000Z"
},
{
"id": 3,
"img": "assets/images/user/user1.jpg",
"name": "task 3",
"title": "5255",
"done": 0,
"note": "55",
"priority": "Normal",
"due_date": "2021-07-21T18:30:00.000Z",
"TaskOwner": 1,
"studentId": "7",
"createdAt": "2021-07-27T15:05:48.000Z",
"updatedAt": "2021-07-27T15:05:48.000Z"
},
{
"id": 4,
"img": "assets/images/user/user1.jpg",
"name": "task 4",
"title": "kaam kro",
"done": 0,
"note": "test note",
"priority": "Normal",
"due_date": "2021-07-21T18:30:00.000Z",
"TaskOwner": 1,
"studentId": "2",
"createdAt": "2021-08-04T14:45:47.000Z",
"updatedAt": "2021-08-04T14:45:47.000Z"
},
The method you are using to parse todos will return a ToDo object casted to a List<ToDo> which will cause an exception!
What you have to do is converting every single map in json to ToDo and then create a List from them.
Here is what you need to do:
replace this line
final List<ToDo> todo = toDoFromJson(response.body) as List<ToDo>;
with this:
final List<ToDo> todo = List<ToDo>.from(response.body.map((x) => toDoFromJson(x)))
fixed this by adding for loop to the Future function, refer to the code below -
Future<List<ToDo>> fetchTodos() async {
List<ToDo> todos = [];
final response =
await http.get(Uri.parse('https://dhulltransport.com:20625/task/all/1'));
if (response.statusCode == 200) {
var jsonList = jsonDecode(response.body);
for (var t in jsonList) {
todos.add(ToDo.fromJson(t));
}
print(todos.length);
return todos;
} else {
return [];
}
}

How to pass a list of json to body of http Post request in Flutter?

I have objects that will filled by a user in a form. I parse these objects to json and add that json in a list to pass in body of request. But i cant do this.
submitQuestions() async {
var headers = {
'Content-Type': 'application/json',
'x-auth-token': '123edrfe33ewed'
};
var request = http.Request('POST', Uri.parse('url'));
request.body = json.encode({
"school_id": "123",
"teacher_id": "123",
"observer_id": "123",
"subject_id": "123",
"subject_name": "abc",
"class_id": "123",
"batch_id": "123",
"topic": "topic",
"academic_year": "2019-2020",
"remarks_data": [
{
"_id": "123",
"heading": "heading",
"Indicators": [
{
"name": "abc",
"_id": "123",
"remark": "abc",
"point": 4
},
{
"name": "abc",
"_id": "123",
"remark": "abc",
"point": 1
}
]
},
{
"_id": "123",
"heading": "abc",
"Indicators": [
{
"name": "abc",
"_id": "123",
"remark": "abc",
"point": 3
}
]
}
]
});
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
}
This json will change dynamically when the number of questions increase. I cannot place this json file in the body like this. How to Do this one.
Wrap each list of json with jsonEncode
like:
"remarks_data": jsonEncode(..)
and do not forget to import.
import 'dart:convert';
The request body try to use Map data type. You can create a model class to deal with it.
Example
class School {
String school_id;
String teacher_id;
String observer_id;
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['school_id'] = this.school_id;
data['teacher_id'] = this.teacher_id;
data['observer_id'] = this.observer_id;
...
return data;
}
}
/// Make sure your _school got data
School _school;
request.body = _school.toJson();

What is the right way to fetch data from network with n:m relation and store both as a model class and reference on each side in flutter?

I spent days to think&googled about how to achieve this, but still can't get any idea how it actually works...
I would appreciate if someone could give me some advise or point me to the right direction.
So in my case, I will fetch a json list from an APIs, and I just wanna store the Shop class into a list which will build in a listView.
Here's my code sample.
Widget buildShopList() {
return ListView.builder(
itemCount: shopList.length,
padding: const EdgeInsets.only(top: 8, bottom: 110),
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
final int count = shopList.length > 10 ? 10 : shopList.length;
return ShopListView(
callback: () {},
shop: shopList[index],
);
},
);
}
class ShopListView extends StatelessWidget {
const ShopListView({Key key, this.shop}: super(key: key);
final Shop shop;
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(shop.type.name),
Text(shop.name),
]
);
}
}
Shop model class
class Shop {
String name;
String website;
String email;
ShopType type;
Shop({this.name, this.website, this.email, this.type});
factory Shop.fromJson(Map<String, dynamic> json) => Shop(
name: json["name"],
type: json["shop_types"],
// can't figure out how to pass the shop type model class into here
website: json["website"],
email: json["email"],
);
Map<String, dynamic> toJson() => {
"name": name,
"shop_types": type,
"website": website,
"email": email
};
}
ShopType model class
class ShopType {
int id;
String name;
String description;
ShopType({this.id, this.name, this.description});
factory ShopType.fromJson(Map<String, dynamic> json) => ShopType(
id: json["id"],
name: json["name"],
description: json["description"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"description": description,
};
}
Here's the json will response from APIs
{
"success": true,
"data": {
"shops": [
{
"id": 1,
"name": "shop name a",
"website": "http://www.test.com/",
"email": "test#test.com",
"description": "this is a dummy data",
"shop_types": [
{
"id": 1,
"name": "Type A",
"description": "Type A",
"pivot": {
"shop_id": 1,
"shop_type_id": 1
}
}
]
},
{
"id": 2,
"name": "shop name b",
"website": "http://www.test.com/",
"email": "test#test.com",
"description": "this is a dummy data",
"shop_types": [
{
"id": 2,
"name": "Store",
"description": "Store",
"pivot": {
"shop_id": 2,
"shop_type_id": 2
}
}
]
},
{
"id": 3,
"name": "shop name c",
"website": "http://www.test.com/",
"email": "test#test.com",
"description": "this is a dummy data",
"shop_types": [
{
"id": 1,
"name": "Type A",
"description": "Type A",
"pivot": {
"shop_id": 3,
"shop_type_id": 1
}
},
{
"id": 2,
"name": "Type B",
"description": "Type B",
"pivot": {
"shop_id": 3,
"shop_type_id": 2
}
}
]
}
],
"shopTypes": [
{
"id": 1,
"name": "Type A",
"description": "Type A",
},
{
"id": 2,
"name": "Type B",
"description": "Type B",
}
]
}
}
Fetch data From network with Dio
fetchShopsAndSaveLocal() async{
var dio = Dio();
dio.options.connectTimeout = 4500 * 10; //45s
dio.options.receiveTimeout = 4500 * 10;
try {
var param = {
"useremail": "dpk.7#gmail.com"
, "password": "123456"};
var response = await dio.post(
"https://api.test/getstores", data: FormData.fromMap(param));
var json = jsonDecode(response.data);
ModelStore store = ModelStore.fromJson(json);
List<Shops> shops = store.shops;
for (var shop in shops) {
saveEverySingleShopInDatabase(shop);
}
} catch (e) {}
}
After that use SQFlite
To Save shops data in Database, after saving data in the local database, fetch data to listview every time from the database.

Flutter return array from response from server

in this part of my code await webApi.getKeywords(); return array which that can get from server, now when i try to return that i get error:
type 'List<dynamic>' is not a subtype of type 'String'
get data from server code:
Future<List<KeywordsResponse>> _getKeywords(BuildContext context) async {
try {
final webApi = Provider.of<WebApi>(context);
final response = await webApi.getKeywords();
List<KeywordsResponse> list = List();
if (response.statusCode == 200) {
list = (json.decode(response.body) as List)
.map((data) => new KeywordsResponse.fromJson(data))
.toList();
return list;
} else {
throw Exception('Failed to load photos');
}
} catch (error) {
print(error);
return null;
}
}
KeywordsResponse class:
#JsonSerializable(nullable: true)
class KeywordsResponse{
#JsonKey(name:'id')
final int id;
#JsonKey(name:'title')
final String title;
#JsonKey(name:'description')
final String description;
KeywordsResponse(this.id, this.title, this.description);
factory KeywordsResponse.fromJson(Map<String, dynamic> json) => _$KeywordsResponseFromJson(json);
Map<String, dynamic> toJson() => _$KeywordsResponseToJson(this);
}
return of response.body:
[
{
"id": 1,
"user_id": 1,
"title": "asdasdasd",
"description": "asdasdasd",
"type": "post",
"slug": "asdasdad",
"featured_images": {
"images": {
"300": "/uploads/post_images/2019/300_1573573784.png",
"600": "/uploads/post_images/2019/600_1573573784.png",
"900": "/uploads/post_images/2019/900_1573573784.png",
"original": "/uploads/post_images/2019/1573573784.png"
},
"thumbnail": "/uploads/post_images/2019/300_1573573784.png"
},
"lang": "fa",
"visit": 0,
"categories": [
{
"id": 1,
"title": "aaaaaaa",
"lang": "fa",
"parent": 0,
"pivot": {
"contents_id": 1,
"content_categories_id": 1
}
}
]
},
{
"id": 2,
"user_id": 1,
"title": "asdasdasd",
"description": "asdadasd",
"type": "post",
"slug": "asdasdasda",
"featured_images": {
"images": {
"300": "/uploads/post_images/2019/300_1573573846.png",
"600": "/uploads/post_images/2019/600_1573573846.png",
"900": "/uploads/post_images/2019/900_1573573846.png",
"original": "/uploads/post_images/2019/1573573846.png"
},
"thumbnail": "/uploads/post_images/2019/300_1573573846.png"
},
"lang": "fa",
"visit": 0,
"categories": [
{
"id": 2,
"title": "bbbbbbbb",
"lang": "fa",
"parent": 0,
"pivot": {
"contents_id": 2,
"content_categories_id": 2
}
}
]
}
]
problem is on this line of code:
json.decode(response.body)
Try this:
list = List<KeywordsResponse>.from(response.body.map((x) => KeywordsResponse.fromJson(x)));