I have a custom object in dart that I convert to json, save as shared preference, then decode it when I need it.
Here is the class:
class MaslulModel {
final String name;
final int numberOfMonths;
final int totalAmount;
final int maslulIndex;
final double interest;
MaslulModel(this.name, this.numberOfMonths, this.totalAmount, this.maslulIndex, this.interest);
String getDetails(){
String output = '2124. Maslul Details: Maslul name: ${name}. Maslul Index: ${this.maslulIndex}. Total amount: ${this.totalAmount}. Number of months: ${this.numberOfMonths}. Interest: ${this.interest}';
return output;
}
// To save list as pref
factory MaslulModel.fromJson(Map<String, dynamic> jsonData) {
return MaslulModel(
jsonData['name'],
jsonData['numberOfMonths'],
jsonData['totalAmount'],
jsonData['maslulIndex'],
jsonData['interest;'],
);
}
static Map<String, dynamic> toMap(MaslulModel maslulModel) => {
'name': maslulModel.name,
'numberOfMonths': maslulModel.numberOfMonths,
'totalAmount': maslulModel.totalAmount,
'maslulIndex': maslulModel.maslulIndex,
'interest': maslulModel.interest,
};
static String encode(List<MaslulModel> musics) => json.encode(
musics
.map<Map<String, dynamic>>((music) => MaslulModel.toMap(music))
.toList(),
);
static List<MaslulModel> decode(String musics) =>
(json.decode(musics) as List<dynamic>)
.map<MaslulModel>((item) => MaslulModel.fromJson(item))
.toList();
}
Now, when I use the decode function, all the values are saved perfectly, by the interest field, which is a double, returns null.
For example, the string that is returned is:
[{"name":"ברמן","numberOfMonths":5,"totalAmount":500,"maslulIndex":0,"interest":5.0}]
Which is great, showing that the interest is 5.0 (a double). But when this is decode, the interest on the object is null.
Why would this be.
Thanks for any help
jsonData['interest;'], is looking for a key of interest;. Didn't think it'd be that simple, huh?
Related
I have a list of elements (Tickets) and since I can't convert the json because of one property (in this case user_id) being a document reference, how can I achieve to change only this property into a string (user_id)? It is written in Dart.
Code that won't work with DocumentReference:
QuerySnapshot<Map<String, dynamic>> querySnapshot.docs
.map((doc) => Ticket.fromJson(doc.data()))
.toList();
fromJson:
Ticket _$TicketFromJson(Map<String, dynamic> json) => Ticket(
id: json['id'] as String? ?? '',
createdAt: DateTime.parse(json['created_at'] as String),
price: (json['price'] as num).toDouble(),
userId: json['user_id'] as String,
);
I know that I can get the String path of the DocumentReference by using .getPath(). But how can alter it inside the map in the query above?
Here is a working solution:
final result = querySnapshot.docs.map((doc) {
final ticket = doc.data();
final dR = ticket['user_id'] as DocumentReference;
final path = dR.path;
ticket.update('user_id', (dynamic value) => path);
return Ticket.fromJson(ticket);
}).toList();
Maybe there is a more elegant way to accomplish the same result.
Trying to create an if statement that checks if an API returns 'items' containing data
Here is the API url, you can see that items is empty for that specific data query https://data.food.gov.uk/food-alerts/id?since=2021-01-04T00:00:00Z
My code is below, been trying to see if I can check 'items' to see if it is null, as well as checking for its length and see if it equals 0 but has not worked so far
class AllergyAlert {
final String title;
AllergyAlert({this.title});
factory AllergyAlert.fromJson(Map<String, dynamic> json) {
if (json['items'] == null) {
return AllergyAlert(
title: 'No new allergy alerts',
);
} else {
return AllergyAlert(
title: json['items'][0]['title'],
);
}
}
}
You can try this
return AllergyAlert(
title: json['items'].isEmpty ? 'No new allergy alerts' : json['items'][0]['title'],
);
First create a class to decode your json string with. You can paste your json here Quicktype
This can then be used with a FutureBuilder to load the data. Here is a full example
Solution
Then after that you will just use the defined names to check. Like:
class Allergen {
Allergen({
this.meta,
this.items,
});
final Meta meta;
final List<dynamic> items;
factory Allergen.fromJson(Map<String, dynamic> json) => Allergen(
meta: Meta.fromJson(json["meta"]),
items: List<dynamic>.from(json["items"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"meta": meta.toJson(),
"items": List<dynamic>.from(items.map((x) => x)),
};
}
class Meta {
Meta({...//more here
you can just check the length of the list
Allergen.items.length==0?//Do This://Else This
I hope I could explain clearly my need, What I have is an API that I connect to and recive a JSON from it.
The Json is nested into a list and an object that have a 2ed tier list.
What i want is to insert this Josn into my local DB (Using SQLite for Flutter).
The point I reached is the inserting of the 1st tier of the json data, but could not insert the data that exist as a list in the 2ed tier. Although I serilize it but the list after when i try to insert, have no mappnig from a list form to the database table fields.
Its like I have [Class User] and [Class Company] A user have many companies rolled in.
When serilaizing the data from the JSON I have the data come to the User Class then nesting to the Companies Class and do the serilaizng for the 2ed tier of the json object then return.
The next step is to insert the data into DB but the data I have in my last object is something like this:
"username" : userName
"company" : CompanyList --- This is a list and cant be inserted into the DB directly in a nested way. As the companylist have multyble fields. and more than one records ex: two companies.
I belive there would be A map to do this in reverse so i could insert it to the DB (I have it in my Company Class) but i cant call it from the place where i try to insert the data into DB due of the differnce in the Classes instances
The instance in my hand is a User Type instance [The main Class between the two], while the companyList if wanted to map it needs a Company insance type.
I can provide code or explain more, any help or idea about the approach may help. Thanks a lot!
#EDIT
This where i try to insert the data into DB
The first inserting is fine but the 2ed one is not.
Future<int> createUserPermissions(UserPermissions userPermissions, ComListPermissions comListPermissions) async {
final db = await dbProvider.database;
var result = db.insert(userPermissionsDBTable, userPermissions.mapToDB());
db.insert(userCompaniesTableDB, comListPermissions.toJson());
return result;
}
User Class
class UserPermissions {
final String userName;
final List<ComListPermissions> comLists;
final bool active;
final String groupName;
final int companyId;
final String permissions;
final ComListPermissions company;
UserPermissions({this.company, this.groupName, this.companyId, this.permissions, this.userName, this.active, this.comLists});
factory UserPermissions.mapFromJsonToDB(Map<String, dynamic> data) {
if (data['comLists'] != null) {
var companyObjJson = data['comLists'] as List;
List<ComListPermissions> _companies = companyObjJson
.map((companyJson) => ComListPermissions.fromJson(companyJson))
.toList();
return UserPermissions(
userName: data['userName'],
active: data['active'],
comLists: _companies,
);
} else {
return UserPermissions(
userName: data['userName'],
active: data['active'],
);
}
}
Map<String, dynamic> mapToDB() => {
"userName": userName,
// "comLists": comLists,
"active": active,
};
}
Comapny Class
class ComListPermissions {
ComListPermissions({
this.groupName,
this.companyId,
this.permissions,
});
String groupName;
int companyId;
String permissions;
//List<String> permissions;
factory ComListPermissions.fromJson(Map<String, dynamic> json) {
if (json['permissions'] != null) {
var permissionsObjJson = json['permissions'] as List;
String s = permissionsObjJson.toString();
return ComListPermissions(
groupName: json["groupName"],
companyId: json["companyID"],
permissions: s,
);
} else {
return ComListPermissions(
groupName: json["groupName"],
companyId: json["companyID"],
);
}
}
Map<String, dynamic> toJson() => {
"groupName": groupName,
"companyID": companyId,
"permissions": permissions,
//"permissions": List<dynamic>.from(permissions.map((x) => x)),
};
}
I Just added a for loop and sent index every time i needed to insert a new recırd into my DB
Future<int> createUserPermissions(UserPermissions userPermissions) async {
final db = await dbProvider.database;
var result = db.insert(userPermissionsDBTable, userPermissions.mapToDB());
int index = userPermissions.comLists.length;
for (int i = 0; i < index; i++) {
db.insert(userCompaniesTableDB, userPermissions.toDatabaseForCompany(i));
}
return result;
}
Map<String, dynamic> toDatabaseForCompany(int index) => {
"companyID": comLists[index].companyId,
"groupName": comLists[index].groupName,
"permissions": comLists[index].permissions,
};
I have a Nested Object like this just a bit bigger:
"name": "String",
"exercise": [
{
"index": 1,
}
],
"pause": [
{"index":2},
]
I convert the exercise and pause to a Json String and save them in a column in SQFLite.
The problem
When I read the Data everything works fine including the List (not nested) but both list's of nested Object are empty when I read a value of the nested object it gives an error.
item.exercise[0].index.toString()
Valid Value range is empty: 0
When I read only item.exercise.toString() it returns []. Without != null ? [...] : List<Exercise>() it also throws an error
Data I get from my Database (shortened)
List of:
[{name: number 1, id: 56, exercise: [{"index":1,"weightGoal":[15,16,17]}, {"index":3,"weightGoal":[15,16,17]}], pause: [{"index":2}]},{"index":4}]}]
What I do with it
Here I try to go through the list and convert it into a List of PlanModel:
List<PlanModel> list =
res.isNotEmpty ? res.map((c) => PlanModel.fromJson(c)).toList() : [];
return list;
Full model
PlanModel planModelFromJson(String str) => PlanModel.fromJson(json.decode(str));
String planModelToJson(PlanModel data) => json.encode(data.toJson());
class PlanModel {
PlanModel({
this.name,
this.id,
this.workoutDays,
this.pastId,
this.timesDone,
this.exercise,
this.pause,
});
String name;
int id;
List<String> workoutDays;
int pastId;
int timesDone;
List<Exercise> exercise;
List<Pause> pause;
factory PlanModel.fromJson(Map<String, dynamic> json) => PlanModel(
name: json["name"],
id: json["id"],
workoutDays: List<String>.from(jsonDecode(json["workoutDays"])),
pastId: json["pastId"],
timesDone: json["timesDone"],
exercise: json["Exercise"] != null ? new List<Exercise>.from(json["Exercise"].map((x) => Exercise.fromJson(x))): List<Exercise>(),
pause: json["Pause"] != null ? new List<Pause>.from(json["Pause"].map((x) => Pause.fromJson(x))): List<Pause>(),
);
Map<String, dynamic> toJson() => {
"name": name,
"id": id,
"workoutDays": List<dynamic>.from(workoutDays.map((x) => x)),
"pastId": pastId,
"timesDone": timesDone,
"Exercise": List<dynamic>.from(exercise.map((x) => x.toJson())),
"Pause": List<dynamic>.from(pause.map((x) => x.toJson())),
};
}
class Exercise {
Exercise({
this.index,
this.name,
this.goal,
this.repGoal,
this.weightGoal,
this.timeGoal,
this.setGoal,
});
int index;
String name;
int goal;
int repGoal;
List<int> weightGoal;
int timeGoal;
List<String> setGoal;
Exercise.fromJson(dynamic json) {
// anything that is wrapped around with this [] in json is converted as list
// anything that is wrapped around with this {} is map
index = json["index"];
name = json["name"];
goal = json["goal"];
repGoal = json["repGoal"];
weightGoal = json["weightGoal"] != null ? json["weightGoal"].cast<int>() : [];
timeGoal = json["timeGoal"];
setGoal = json["setGoal"] != null ? json["setGoal"].cast<String>() : [];
}
Map<String, dynamic> toJson() => {
"index": index,
"name": name,
"goal": goal,
"repGoal": repGoal,
"weightGoal": List<dynamic>.from(weightGoal.map((x) => x)),
"timeGoal": timeGoal,
"setGoal": List<dynamic>.from(setGoal.map((x) => x)),
};
}
class Pause {
Pause({
this.index,
this.timeInMilSec,
});
int index;
int timeInMilSec;
factory Pause.fromJson(Map<String, dynamic> json) => Pause(
index: json["index"],
timeInMilSec: json["timeInMilSec"],
);
Map<String, dynamic> toJson() => {
"index": index,
"timeInMilSec": timeInMilSec,
};
}
Read this first.
You need to tweek this code a little to work for you but the idea is that;
also read comment in the code.
if json string comes with [] those around, json.decode will decode it as List<Map>.
if it comes with {} this json.decode will decode it as Map.
note: be careful while using generics on json.decode I reccommend not to.
data inside the jsonString does not really corresponds with the values inside the fromJson function. json string which you have provided was not really good. so I think you will understand how to manipulate it for your needs.
also main constructor Exercise you can use for initial data.
import 'dart:convert';
class Exercise{
Exercise({this.index,
this.name,
this.repGoal,
this.weightGoal,
this.setGoal});
String index;
String name;
String repGoal;
String weightGoal;
String setGoal;
Exercise.fromJson(dynamic json) :
// anything that is wrapped around with this [] in json is converted as list
// anything that is wrapped around with this {} is map
index = json["exercise"][0]["index"].toString(),
name = json["name"].toString(),
repGoal = json["repGoal"].toString(),
weightGoal = json["weightGoal"].toString(),
setGoal = json["setGoal"].toString();
}
void main(){
String jsonString = '{name: number 1, id: 56, exercise: [{"index":1,"weightGoal":[15,16,17], pause: [{"index":2}]}';
Map json = json.decode(jsonString);
Exercise.fromJson(json);
}
I found it out :)
I have restructured my fromJson to this, especially the jsonDecode was important, because json["exercise "] was only a String.
PlanModel.fromJson(dynamic json) {
name = json["name"];
if (json["exercise"] != null) {
exercise = [];
jsonDecode(json["exercise"]).forEach((v) {
exercise.add(Exercise.fromJson(v));
});
}}
now I can access it with
PlanModel item = snapshot.data[index];
item.exercise[0].timeGoal.toString()
I'm working with a RESTful API that seems to be working and used in other applications that gives me something like this:
"notes": [
[
{
"automaticNote": false,
"contactId": 0,
"caseFileId": 0,
"dateCreated": "2019-05-02",
"deletedTime": "2019-05-02T19:31:54.588Z"
}
]
]
The double pair of square brackets means that one pair of the square brackets has no name/key associated with it. To make matters worse, notes is itself nested in some complex JSON.
I tried using JSON to Dart but it throws an error. So really my question is, how do I serialize a JSON array that has no key/name?
I'd normally do it like this:
class Note {
bool automaticNote;
int contactId;
int caseFileId;
String dateCreated;
String deletedTime;
Note(
{this.automaticNote,
this.contactId,
this.caseFileId,
this.dateCreated,
this.deletedTime});
Note.fromJson(Map<String, dynamic> json) {
automaticNote = json['automaticNote'];
contactId = json['contactId'];
caseFileId = json['caseFileId'];
dateCreated = json['dateCreated'];
deletedTime = json['deletedTime'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['automaticNote'] = this.automaticNote;
data['contactId'] = this.contactId;
data['caseFileId'] = this.caseFileId;
data['dateCreated'] = this.dateCreated;
data['deletedTime'] = this.deletedTime;
return data;
}
}
But the double JSON array is throwing me off (and again, notes itself is nested in a more complex JSON object but for the sake of simplicity I did not include the whole thing here).
Thanks!
After decoding, notes is a member of some Map<String, dynamic> as usual. Let's call that m.
So m['notes'] is a list, who's first member, m['notes'][0] is also a list. Its first member, m['notes'][0][0] is another Map<String, dynamic>, which is what you need for your constructor.
You should therefore be able to use:
Note n = Note.fromJson(m['notes'][0][0]);
Let's take the case of you saving automaticNote;
automaticNote = json['notes'][0][0]['automaticNote'];
This offers the key for notes which has an array where your data is at the first point or index 0 (of notes hence [0]) and within that array there is another array which has your data. Again it's the first array item so, [0] and then you're finally at the level with your data so you then use your key for automaticNote, ['automaticNote'].
Note.fromJson(Map<String, dynamic> json) {
automaticNote = json[0][0]['automaticNote'];
contactId = json[0][0]['contactId'];
caseFileId = json[0][0]['caseFileId'];
dateCreated = json[0][0]['dateCreated'];
deletedTime = json[0][0]['deletedTime'];
}