Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed last month.
Improve this question
I have following code:
I use cloud firestore as database
UserModel:
class DbUser {
String id;
final String authUserID;
final String userName;
final List<String>? itemsForSale;
final List<String>? itemFavourites;
final List<String>? bids;
DbUser(
{this.id = '',
required this.authUserID,
required this.userName,
this.itemsForSale,
this.itemFavourites,
this.bids});
Map<String, dynamic> toJson() => {
'id': id,
'authUserID': authUserID,
'userName': userName,
'itemsForSale': itemsForSale,
'itemFavourites': itemFavourites,
'bids': bids,
};
static DbUser fromJson(Map<String, dynamic> json) => DbUser(
id: json['id'],
authUserID: json['authUserID'],
userName: json['userName'],
itemsForSale: json['itemsForSale'] is Iterable
? List.from(json['itemsForSale'])
: null,
itemFavourites: json['itemFavourites'] is Iterable
? List.from(json['itemFavourites'])
: null,
bids: json['bids'] is Iterable ? List.from(json['bids']) : null,
);
}
Repository class
final _firestoreDB = FirebaseFirestore.instance;
Future<DbUser?> getDBUserByDBUserId({required String dbUserID}) async {
final docUser = _firestoreDB.collection('users').doc(dbUserID);
final snapshot = await docUser.get();
if (snapshot.exists) {
return DbUser.fromJson(snapshot.data()!);
}
return null;
}
snapshot.exists returns false.
I do not understand why?
my snapshot returns null but I do not see why it does that, could somebody please help me?
Thank you
Space
found my problem, there was a space before my Id that had been retreived, I must have accedentally put it there when creating the database...
Looking at the screenshot of the document you shared, the document ID in the second column is different from the value of authUserID in the third column. So it seems like you added the document by calling add, which means that Firestore generates a unique ID for you.
You then create a reference to the document with this code:
_firestoreDB.collection('users').doc(dbUserID)
But here you are specifying dbUserID as the document ID, which doesn't match what you did when you created the document. Firestore now looks for a document with an ID that is the same as the user ID, which doesn't exist and thus gives you a snapshot where exists is false.
If you want to find the document for the user in your current structure, you can use a query to do so:
Future<DbUser?> getDBUserByDBUserId({required String dbUserID}) async {
final query = _firestoreDB.collection('users').where('authUserID', isEqualTo: dbUserID)
final snapshot = await query.get();
if (snapshot.size > 0) {
return DbUser.fromJson(snapshot.docs[0]!.data()!);
}
return null;
}
But a better solution might be to actually store the user document under its user ID. You can specify the document ID as shown in the documentation on setting a document. So here you'd call .document('theuserid').set(...) instead of add(...).
Related
Please I would appreciate if anyone can help me solve this problem so I can display data from firestore correctly in my flutter app.
I have the model as shown below to send data to firestore
class Vital {
String id;
final String bloodSugar;
final String bloodPressure;
final String bodyTemp;
final DateTime? createdOn;
Vital({
this.id = '',
required this.bloodSugar,
required this.bloodPressure,
required this.bodyTemp,
required this.createdOn,
});
Map<String, dynamic> toJson() => {
'id': id,
'bloodSugar': bloodSugar,
'bloodPressure': bloodPressure,
'bodyTemp': bodyTemp,
"createdOn": Utils.fromDateTimeToJson(createdOn)
};
Vital.fromSnapShot(DocumentSnapshot<Map<String, dynamic>> snapshot)
: id = snapshot.id,
bloodSugar = snapshot.data()!["bloodSugar"],
bloodPressure = snapshot.data()!["bloodPressure"],
bodyTemp = snapshot.data()!["bodyTemp"],
createdOn = snapshot.data()!["createdOn"].toDate();
}
I send the data to firestore using the below code
final FirebaseAuth auth = FirebaseAuth.instance;
final User? user = await auth.currentUser;
final uid = user?.uid;
final vitals = FirebaseFirestore.instance
.collection('vitalsign')
.doc(uid)
.collection("usersVitals");
final vital = Vital(
createdOn: DateTime.now(),
bloodSugar: _bloodSugar.text,
bloodPressure: _bloodPressure.text,
bodyTemp: _bodyTemp.text);
final json = vital.toJson();
await vitals.add(json);
But the issue now is I want to get the data and display it in my ui using stream builder but I would like that all the data from the bloodSugar field be displayed separatly in a row wrap with a container.
I would also like that all data from bloodPressure field be displayed separatly in a row wrap with a container.
To explain better, What I want to achieve is
Container 1 which is bloodSugar alone should have : bloodSugar1, bloodSugar2, bloodSugar3 and so on as a row items.
Container 2 which is bloodPressure alone should have : bloodPressure1, bloodPressure2, bloodPressure3 and so on.
then thesame for bloodTemp.
so the result should be like
Column(
children: [
container1 for bloodSugar,
container2 for bloodPressure,
Container3 for bodyTemp,
I have tried using listview.builder but I have not been able to get the data from different field to be separated from each other.
I was wondering how I can read from a firebase database once. I want to be able to read from a document that has the same ID as the user that's logged in, via the firebase authentication, and then return the string of the user's name.
Right now I am getting 3 errors on line 12 under the get method
Function expressions can't be named
Expected an identifier
The getter '(' isn't defined for the type 'DocumentRefence<Object?>'
class DatabaseService {
final CollectionReference usersCollection = FirebaseFirestore.instance.collection("users");
final String uid;
DatabaseService(this.uid);
Future<String> getUserName() async {
String name = '';
var document = await usersCollection.doc(uid);
document.get() => then((doc) {
name = doc('name');
});
return name;
}
}
async/await should use of api calls not on the database path reference.
Just make sure of the snapshap.data() is correct, otherwise you can use my code as a reference.
Future<String> getUserName() async {
var document = usersCollection.doc(uid);
var snapshot = await document.get();
Map<String, dynamic> data = snapshot.data();
name = data['name'];
return name;
}
This may sound stupid but I am confused. How are you supposed to save data to Firestore?
Is it supposed to be converted to/from JSON before adding and retrieving? Or is it supposed to be saved as a map, like:
({'sugars': sugars, 'name': name, 'strength': strength})
Is it different for real-time DB?
I have seen people adding the following to their model classes:
final FieldModel field;
final int number;
final String id;
TransactionModel({
required this.field,
required this.number,
this.id = '',
});
/// this conversion to JSON
factory TransactionModel.fromJson(String id, Map<String, dynamic> json) =>
TransactionModel(
field: FieldModel.fromJson(json['field']['id'], json['field']),
id: id,
number: json['number'],
);
My question is: Why do they convert it to JSON? Is it always required? Is this for Firestore or Realtime Database?
You can find all the details about fetching and storing data in Cloud Firestore here.
Firestore stores data within "documents", which are contained within "collections". Documents can also contain nested collections. For example, our users would each have their own "document" stored inside the "Users" collection. The collection method allows us to reference a collection within our code.
To add an entry to Firestore you need to pass a Map<String, dynamic> to either the add() function of the collection or set() function of the document.
You can do something like this to send data.
await FirebaseFirestore.instance.collection('users').add({
'full_name': fullName, // John Doe
'company': company, // Stokes and Sons
'age': age // 42
});
Or, you can alternatively do:
await FirebaseFirestore.instance.collection('users').add(
userModel.toJson(),
);
where, toJson() is
Map<String, dynamic> toJson() => {
"full_name": fullName,
"company": company,
"age": age,
};
To read a collection or document once, call the Query.get or DocumentReference.get methods.
class GetUserName extends StatelessWidget {
final String documentId;
GetUserName(this.documentId);
#override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('users');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.hasData && !snapshot.data!.exists) {
return Text("Document does not exist");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text("Full Name: ${data['full_name']} ${data['last_name']}");
}
return Text("loading");
},
);
}
}
As to answer your question:
My question is: Why do they convert it to json? Is it always required? Is this for Firestore or Realtime Database?
JSON (JavaScript Object Notation) is a lightweight format that is used
for data interchanging. It is based on a subset of JavaScript language
(the way objects are built-in JavaScript). As stated in the MDN, some
JavaScript is not JSON, and some JSON is not JavaScript.
An example of where this is used is web services responses. In the
'old' days, web services used XML as their primary data format for
transmitting back data, but since JSON appeared (The JSON format is
specified in RFC 4627 by Douglas Crockford), it has been the preferred
format because it is much more lightweight
You can refer to this answer for more information on JSON.
To sum up, JSON or Maps are used for data transfers as this provides the data in a well-structured way (key-value pair). And it's easy to read compared to other data transfer formats like CSV.
Overview:
App architecture details:
state management -> provider (not sure this is relevant, but in case you are interested)
data storage -> SQFlite
Specific issue details:
I have a calendarDay data model, with a property of
DateTime date;
I know that DateTime is not supported in SQLite (not in SQFlite either) and the recommendation is to use a String or Integer . I am struggling with how to actually do that.
Error I am getting:
flutter: *** WARNING ***
Invalid argument 2021-07-01 15:09:11.129598 with type DateTime.
Only num, String and Uint8List are supported. See https://github.com/tekartik/sqflite/blob/master/sqflite/doc/supported_types.md for details
This will throw an exception in the future. For now it is displayed once per type.
This is my setup:
calendar_day.dart
class CalendarDay {
int? id;
DateTime date;
CalendarDay(
{this.id,
required this.date});
// encode to SQLite database
Map<String, dynamic> toMap() {
final map = Map<String, dynamic>();
map['id'] = id;
map['date'] = date.toIso8601String(); //toString(); this toString did not work //jsonEncode(date) -> SERIALIZE THE ARRAYS INTO JSON strings, this did not work
return map;
}
// decode from SQLite database
static fromMap(Map map) {
return CalendarDay(
id: map['id'],
date: DateTime.parse(map['date']), // jsonDecode(map['date']));
}
}
database_client.dart
class DatabaseClient {
Future<Database> initializedDatabase() async {
WidgetsFlutterBinding.ensureInitialized();
String path = await getDatabasesPath();
return openDatabase(
join(path, 'three_things_database.db'),
onCreate: (database, version) async {
await database.execute(
"CREATE TABLE ${Strings.calendarDayDataBase} (id INTEGER PRIMARY KEY, date TEXT)",
); },
version: 1, ); }
// Create / insert calendarDay
Future<void> insertCalendarDay(CalendarDay day) async {
final Database database = await initializedDatabase();
await database.insert(
Strings.calendarDayDataBase,
day.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
}
I am thinking the problem lies with the toMap() method, since the error notes the DateTime object. But I am a bit stuck and don't really know how to get around this. Any help is greatly appreciated.
Additional things I have tried in toMap() :
I did include the code commented out, but for clarity, I'll post here:
I tried mapping the DateTime object to a JSONString. This would hopefully be enough for storing the map in SQLite database, but this approach threw the same error.
Tried mapping to a regular String using date.toString(). This did not work either. Since the recommendation (link above) from the SQFlite folks is to use ISO8601 string, I thought this approach would work.
Related question(s), yet did not solve my question:
Create DateTime column in SQFlite
Here's a clear example :
var dt = DateTime.now();
// String
var dtStr = dt.toIso8601String();
dt = DateTime.tryParse(dtStr);
// Int
var dtInt = dt.millisecondsSinceEpoch;
dt = DateTime.fromMillisecondsSinceEpoch(dtInt);
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I am trying to get user from Json,but somehow i get en error that says
the method 'map' was called on null. flutter
I don't know why,here are my codes for my models:
class User {
final String id;
final String email;
final String username;
List<FollowUserModel> following = [];
List<FollowUserModel> followers = [];
User({this.id,this.email,this.followers,this.following, this.username});
factory User.fromJSON(Map<String, dynamic> jsonMap) {
return User(
id: jsonMap['id'] as String,
email: jsonMap['email'] as String,
username: jsonMap['username'] as String,
following: jsonMap["following_set"] != null ? List<FollowUserModel>.from( jsonMap["followiing_set"].map((x) => FollowUserModel.fromJSON(x))) :[],
followers: jsonMap["followers_set"] != null ? List<FollowUserModel>.from( jsonMap["followers_set"].map((x) => FollowUserModel.fromJSON(x))) :[],
);
}
}
class FollowUserModel {
final String id;
final User author;
final User profile;
FollowUserModel({this.id,this.author,this.profile});
factory FollowUserModel.fromJSON(Map<String, dynamic> jsonMap) {
return FollowUserModel(
id: jsonMap['id'] as String,
author: jsonMap['author'] as User,
profile: jsonMap['profile'] as User,
);
}
}
And here is my full error code from my exception:
I declared the arrays as [] before as i expect some null returns but still,i get the error. Anybody knows the reason?
Update
I know i made typo,but still the error exists.
You made typos, instead of 'following_set' and 'followers_set' you have written 'followiing_set' and 'followrse_set':
....
following: jsonMap["following_set"] != null ? List<FollowUserModel>.from( jsonMap["followiing_set"].map((x) => FollowUserModel.fromJSON(x))) :[],
followers: jsonMap["followers_set"] != null ? List<FollowUserModel>.from( jsonMap["followrse_set"].map((x) => FollowUserModel.fromJSON(x))) :[],
....