How to extract data recursively from firestore? - flutter

I have some documents in Firestore that contain references to other documents in other collections, I'm trying to extract one object (called order) that should look like:
{
"field1": "value1",
"field2": "value2",
...
"offer": {
"field1": "value1",
"field2": "value2",
...
"address": "string value"
}
}
I wrote this function:
Future<Map<String, dynamic>> getDetailsByDocumentReference(
DocumentReference ref) async {
final document = await ref.get();
final data = document.data() as Map<String, dynamic>;
final Map<String, dynamic> result = {};
data.forEach((field, value) async {
if (value is DocumentReference) {
result[field] = await getDetailsByDocumentReference(value);
} else {
result[field] = value;
}
});
return result;
}
The function is called this way:
Future<Map<String, dynamic>> getOrderDetailsById(String id) async {
DocumentReference<Map<String, dynamic>> docRef = _db.doc('orders/$id');
Map<String, dynamic> result = await getDetailsByDocumentReference(docRef);
return result;
}
The final result is only a map with one values that are not references
{
"field1": "value1",
"field2": "value2"
}
All async calls are made with await, what am I missing?

I don't see you referencing the collection anywhere. It seems this:
DocumentReference<Map<String, dynamic>> docRef = _db.doc('orders/$id');
Should instead be this:
DocumentReference<Map<String, dynamic>> docRef = _db.collection('orders').doc(id);
Get a document in Firestore with Fluter

Related

Flutter audio_service add item from json

audio_service new update removed fromjson in model class .. how can i add media item from json? My json look like this
[
{
"id": "http://581.22.00.66:8500/1?type=http",
"title": "test",
"artist": "test",
"album": "test",
"artUri": "test.png",
"genre": "8535",
"displayDescription": "23"
},
{
"id": "http://581.22.00.66:6600/2?type=http",
"title": "test2",
"artist": "test2",
"album": "test2",
"artUri": "test2.png",
"genre": "1498",
"displayDescription": "23"
},
we using dio for json.
List<MediaItem> _queue = [];
void getdata() async {
final response = await Dio().get(Constants.url+'post.php', queryParameters: {
});
for (int i = 0; i < response.data.length; i++) {
_queue.add(response.data[i]);
}
}
Error:
Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'MediaItem'
If there is no default method to do that, you can create a JSON(map) parser function to audio_service's Media model.
Note: parser function converts only the fields that you provide on your json data.
MediaItem jsonToMeidaItem(Map data) {
return MediaItem(
id: data['id'].toString(),
title: data['title'].toString(),
artist: data['artist'].toString(),
album: data['album'].toString(),
artUri: data['artUri'].toString(),
genre: data['genre'].toString(),
displayDescription: data['displayDescription'].toString(),
);
}
Then you could be able to convert JSON data to MediaItem.
Substituted converter-function to your code:
List<MediaItem> _queue = [];
void getdata() async {
final response = await Dio().get(Constants.url+'post.php', queryParameters: {
});
for (int i = 0; i < response.data.length; i++) {
final MediaItem mediaItem = jsonToMeidaItem(response.data[i]);
_queue.add(mediaItem);
}
}

PageView.Builder in Flutter The getter 'length' was called on null. Receiver: null Tried calling: length

when use response from API then show error
The getter 'length' was called on null.
Receiver: null
Tried calling: length
here is my API code
var url =
"https://domain.php";
var res;
var splashs;
void initState() {
super.initState();
fetchData();
}
fetchData() async {
res = await http.get(url);
splashs = jsonDecode(res.body);
setState(() {});
}
while use List then code working properly
List<Map<String, String>> splashs = [
{
"header": "Flatros",
"text": "Welcome to Flatros, Let’s shop!",
"image_name": "assets/images/splash_1.png"
},
{
"header": "Shopping",
"text":
"We help people conect with store \naround United State of America",
"image_name": "assets/images/splash_2.png"
},
{
"header": "Multi Category",
"text": "FInal Screen",
"image_name": "assets/images/splash_3.png"
},
];
May be you need to convert your data into List or Array
List splashs = new List();
fetchData() async {
res = await http.get(url);
final data = jsonDecode(res.body);
for (var i in data) {
splashs.add(i); // Create a list and add data one by one
}
setState(() {});
}

Push array into list flutter

So i'm trying to create a list with objects of type 'MessageListItem'. I'm trying to push data returned from my API into the list. The variable I want it pushed into is 'messages'. I am getting an error in the 'getMessages()' function.
The error I am getting is: A value of type 'MessageListItem' can't be assigned to a variable of type 'List'.
The API call & code is:
List<MessageListItem> messages;
getMessages() async {
List<MessageListItem> res = MessageListItem.fromJson(await getMessageList());
// I'm getting the error on the line above.
print(res);
}
Future<dynamic> getMessageList() async {
final response = await http.get(baseUrl + 'message/jxchumber');
print(response.statusCode);
if (response.statusCode == 200) {
var res = json.decode(response.body);
return res;
} else {
throw Exception('Failed to get data');
}
}
MessageListItem Class
class MessageListItem {
int id;
int senderId;
int recipientId;
String senderUsername;
String recipientUsername;
int itemId;
String messageContentString;
bool read;
dynamic dateTimeSent;
MessageListItem(
{this.id,
this.senderId,
this.recipientId,
this.senderUsername,
this.recipientUsername,
this.itemId,
this.messageContentString,
this.read,
this.dateTimeSent});
factory MessageListItem.fromJson(Map<String, dynamic> json) {
return MessageListItem(
id: json['id'],
senderId: json['senderId'],
recipientId: json['recipientId'],
senderUsername: json['senderUsername'],
recipientUsername: json['recipientUsername'],
itemId: json['itemId'],
messageContentString: json['messageContentString'],
read: json['read'],
dateTimeSent: json['dateTimeSent'],
);
}
}
The data being returned from the API is:
[
{
"id": 4,
"senderId": 1,
"recipientId": 3,
"senderUsername": "jxchumber",
"recipientUsername": "pavster31",
"itemId": 0,
"messageContentString": "hello1",
"read": false,
"dateTimeSent": "2020-12-14T22:23:55.1473414"
},
{
"id": 3,
"senderId": 1,
"recipientId": 9,
"senderUsername": "jxchumber",
"recipientUsername": "larsen",
"itemId": 0,
"messageContentString": "hello1",
"read": false,
"dateTimeSent": "2020-12-14T16:04:50.8232055"
}
]
I'm trying to push it into the variable 'messages'
Try this
getMessages() async {
var list = await getMessageList();
List<MessageListItem> res = list.map((i)=>MessageListItem.fromJson(i)).toList();
}

Firestore document to Flutter Problem : Exception( type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>')

Can't get my head around this problem.
I set the following document to firestore.
And i need to convert 'attendance' field to a List.
Map<String, dynamic> data = {
"name": "memberName",
"attendance": {
"0": {"morning": false, "noon": true, "night": true},
"1": {"morning": false, "noon": true, "night": true}
},
"deposits": {
"0": {"date": "date", "amount": 100},
"1": {"date": "date", "amount": 100}
}
};
Using StreamProvider . Stream has no problem.
using toList()
Documents are fetched. But models are failing. Getting a Exception : [type '_InternalLinkedHashMap' is not a subtype of type 'Map']
Model Classes:
class Member {
String id;
String name;
List<Attendance> attendances;
List<Deposit> deposits;
Member({this.id, this.name, this.attendances, this.deposits});
Member.fromSnapshot(DocumentSnapshot doc) {
Map<String, dynamic> json = doc.data;
id = doc.documentID;
name = json['name'];
if (json['attendance'] != null) {
Map<String, dynamic> atdmap = json['attendance'];
attendances = new List<Attendance>();
atdmap.forEach((k, v) {
attendances.add(new Attendance.fromJson(v));
});
}
if (json['deposits'] != null) {
Map<String, dynamic> dmap = json['deposits'];
deposits = new List<Deposit>();
dmap.forEach((k, v) {
deposits.add(new Deposit.fromJson(v));
});
}
}
}
class Attendance {
bool morning;
bool noon;
bool night;
Attendance({this.morning, this.noon, this.night});
Attendance.fromJson(Map<String, dynamic> json) {
morning = json['morning'];
noon = json['noon'];
night = json['night'];
}
}
class Deposit {
String date;
int amount;
Deposit({this.date, this.amount});
Deposit.fromJson(Map<String, dynamic> json) {
date = json['date'];
amount = json['amount'];
}
}
Where is it getting wrong. need a little help.
thank you.
try an explicit cast
Map<String, dynamic> json = doc.data as Map<String, dynamic>;

How do i convert a String to a List<Map<String,String>>

I have a list which contains several keys and values, which are then mapped into a DataTable to be displayed.
List<Map<String, String>> listOfColumns = [
{"Name": "John", "Number": "1", "State": " "},
{"Name": "Brad", "Number": "2", "State": " "},
{"Name": "Ryan", "Number": "3", "State": " "},
{"Name": "Grant", "Number": "4", "State": " "},
];
Now, i want the data in the data table to be saved. So I simply used the File IO system i created an asynchronous function called _save() and _read(), in _save() i converted listOfColumns to a string.
_read() async {
try {
final directory = await getExternalStorageDirectory();
final file = File('${directory.path}/my_file.txt');
text = await file.readAsString();
} catch (e) {
print("Couldn't read file");
}
}
_save() async {
final directory = await getExternalStorageDirectory();
final file = File('${directory.path}/my_file.txt');
final List<Map<String, String>> data = listOfColumns;
await file.writeAsString(data.toString());
print('saved');
}
Now when it comes to reading the data from the file, here's the thing - How do i actually turn the variable text back into List<Map<String,String>>? Im totally lost on how to achieve this. Any help is highly appreciated. Thanks.
You should actually save it as JSON in the first place (using jsonEncode and then you can easily convert it back:
Future<void> _save() async {
...
final jsonString = jsonEncode(listOfColumns);
await file.writeAsString(jsonString);
}
Now, you can easily load your data using jsonDecode:
Future<void> _read() async {
...
final decoded = jsonDecode(await file.readAsString()) as List;
listOfColumns = decoded.cast<Map<String, dynamic>>()
.map((map) => map.cast<String, String>()).toList();
}