Convert DocumentReference property into String from Firestore - json

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.

Related

Flutter freezed convert List to json

this is my two freezed class which i want to make a simple json from ContactsData
#freezed
class ContactsData with _$ContactsData {
const factory ContactsData({
String? displayName,
String? givenName,
String? familyName,
String? company,
String? jobTitle,
List<ContactPhone>? phones,
}) = _ContactsData;
factory ContactsData.fromJson(Map<String, dynamic> json) => _$ContactsDataFromJson(json);
}
#freezed
class ContactPhone with _$ContactPhone {
const factory ContactPhone({
String? label,
String? value,
}) = _ContactPhone;
factory ContactPhone.fromJson(Map<String, dynamic> json) => _$ContactPhoneFromJson(json);
}
i added some data into allContacts by this code:
late List<ContactsData> allContacts=[];
contacts?.forEach((c) {
List<ContactPhone> phones=[];
c.phones!.forEach((f) =>phones.add(ContactPhone(label: f.label,value: f.value)));
allContacts.add(
ContactsData(
displayName:c.displayName,
givenName: c.givenName,
familyName: c.familyName,
company: c.company,
jobTitle: c.jobTitle,
phones: phones,
)
);
});
now how can i convert allContacts to json like with this code:
allContacts.toJson();
build.yaml:
targets:
$default:
builders:
json_serializable:
options:
explicit_to_json: true
allContacts is just a regular List.
Either:
make it an object (possibly even a freezed object) similar to ContactsData and call it something like ContactsCollection or something better... and add toJson method to it.
Or
Do something like jsonEncode(allContacts.map((c) => c.toJson()).toList())

parsing airtable json to flutter podo

I'm new in flutter and I have issue with parsing JSON on HTTP response.
I'm using Airtable backend, to store information about posts. These always contain images, and sometimes attachments - PDFs.
I built PODO, like this:
class Post {
String recordid;
String timecreated;
String title;
String content;
String imgurl;
List<Pdf>? pdf;
Post({
required this.recordid,
required this.timecreated,
required this.title,
required this.content,
required this.imgurl,
required this.pdf
});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
// fields: Fields.fromJson(json['fields']),
recordid: json['id'] as String,
timecreated: json['createdTime'] as String,
title: json['fields']['field1'] as String,
content: json['fields']['field2'] as String,
imgurl: json['fields']['IMG'][0]['url'] as String,
pdf: json['fields']['PDF'] == null ? null : List<Map<String, dynamic>>.from(json['fields']['PDF']).map((dynamic value) => Pdf.fromJson(value)).toList()
);
}
Map<String, dynamic> toJson() => {
"recordid": recordid,
"timecreated": timecreated,
"title": title,
"content": content,
"imgurl": imgurl,
"pdf": pdf
// "fields": List<dynamic>.from(fields.map((x) => x.toJson())),
};
}
class Pdf {
Pdf({
required this.url,
required this.filename
});
Pdf.fromJson(Map<String, dynamic> json) :
url = json['url'],
filename = json['filename'];
final String? url;
final String? filename;
}
I'm not getting any errors, but when I'm trying to use PDF URL in UI, eg. in Text:
ListTile(title: Text(post.pdf.url)),
I'm getting error:
The property 'url' can't be unconditionally accessed because the
receiver can be 'null'.
I'm aiming to create a button on a page, that is clickable when PDF URL exists. When it exists, button navigates to PDF view that use PDF URL to get and display PDF.
Any ideas?
The pdf attribute is nullable, hence it cannot be accessed unconditionally. This is assuming you somehow have the pdf not as a list, otherwise you would need to index your list, your code is incomplete. You could try to do something like this:
if (post.pdf != null) {
//wrap it with a button or whatever
return ListTile(title: Text(post.pdf!.url));
}
else {
return Text('no pdf');
}
Well, sth seems to work, but still cannot parse pdf URL.
I'm getting Text "sth is there" when post.pdf != null and it works, but when I'm changing to get value from model using post.pdf!.url I'm getting same error:
Try correcting the name to the name of an existing getter, or defining
a getter or field named 'url'.
child:Text(post.pdf!.url));
Here's piece of code:
LayoutBuilder(builder: (context, constraints) {
if(post.pdf != null){
return ElevatedButton(onPressed: () => Navigator.of(context).push(
MaterialPageRoute(builder: (context) => PDFview(pdf: [])
)),
child:Text(post.pdf!.url));
}else{
return ElevatedButton(onPressed: null,
child:Text("no PDF"));
}
}
)
A fix in PODO worked for me.
Here's solution for my problem :)
pdf: json['fields']['PDF'] == null ? null : json['fields']['PDF'][0]['url'] as String,

Dart. Decode json double gives null

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?

How to check if JSON array is empty in Flutter

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

Flutter converting Nested Object from Json returns null

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()