I have an existing Firestore database for a project. In a given collection (say "users"), I have the user profile information in each document.
In some documents, I have the field "signupMethod" in the collection while the same field does not exist in some other documents in the same collection.
I need to try to read the signupMethod for each user session in my application. If the document does have the field, the value of the field needs to be used. If the field for the corresponding users document does not exist, I would like to set it to the default value of "Email".
I try the following approach:
try {
if (snapshot.data().containsKey("signupMethod")) {
wpUserProfile.signupMethod = snapshot.data["signupMethod"];
} else {
wpUserProfile.signupMethod = "Email";
}
} on Exception catch (_) {
wpUserProfile.signupMethod = "Email";
}
But it gives the following error:
Exception has occurred.
NoSuchMethodError (NoSuchMethodError: Class '_JsonDocumentSnapshot' has no instance method 'call'.
Receiver: Instance of '_JsonDocumentSnapshot'
Tried calling: call())
And I try the following instead:
try {
wpUserProfile.signupMethod = snapshot.data["signupMethod"];
} on Exception catch (_) {
wpUserProfile.signupMethod = "Email";
}
And I get the following error this time:
Exception has occurred.
StateError (Bad state: field does not exist within the DocumentSnapshotPlatform)
I do not understand why it does not run the code in the Exception block and set it to "Email".
Does anyone know how I should handle this situation when reading a field from Firestore which may or may not exist in a given document with flutter?
ADDENDUM: (Answer to Peter's question below)
If I print out snapshot.data
, I get the following output:
flutter: Instance of '_JsonDocumentSnapshot'
If I print out snapshot.data()
, I get the following error:
[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: NoSuchMethodError: Class '_JsonDocumentSnapshot' has no instance method 'call'.
Receiver: Instance of '_JsonDocumentSnapshot'
Tried calling: call()
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:63:5)
#1 _UserDataProviderState._setUserProfileData
package:wp/widgets/user_data_provider.dart:76
#2 _UserDataProviderState.build.<anonymous closure>
package:wp/widgets/user_data_provider.dart:135
#3 _FutureBuilderState.build
package:flutter/…/widgets/async.dart:782
#4 StatefulElement.build
package:flutter/…/widgets/framework.dart:4782
#5 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4665
#6 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:4840
#7 Element.rebuild
package:flutter/…/widgets/framework.dart:4355
#8 BuildOwner.buildScope
package:flutter/…/widgets/framework.dart:2620
#9 WidgetsBinding.drawFrame
package:flutter/…/widgets/binding.dart:882
#10 RendererBinding._handlePersistentFrameCallback
package:flutter/…/rendering/binding.dart:319
#11 SchedulerBinding._invokeFrameCallback
package:flutter/…/scheduler/binding.dart:1143
#12 SchedulerBinding.handleDrawFrame
package:flutter/…/scheduler/binding.dart:1080
#13 SchedulerBinding._handleDrawFrame
package:flutter/…/scheduler/binding.dart:996
#14 _rootRun (dart:async/zone.dart:1428:13)
#15 _CustomZone.run (dart:async/zone.dart:1328:19)
#16 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
#17 _invoke (dart:ui/hooks.dart:166:10)
#18 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:270:5)
#19 _drawFrame (dart:ui/hooks.dart:129:31)
If I just print out snapshot.data["email"]
, I get the following output:
testuser@testuser.com
CodePudding user response:
In your case I assume that snapshot
contains an AsyncSnapshot
object. According to the documentation it has a data
property. This can be null
, so it is always recommended to check hasData
/ hasError
properties before processing the results.
So once you made sure it is not null, snapshot.data!
will contain the result of your AsyncSnapshot
, in this case this is a DocumentSnapshot
.
Looking at documentation, DocumentSnapshot
has a data()
method that will hold the document itself. So finally snapshot.data!.data()
will be your document, and you can get the fields from it like:
snapshot.data!.data()["signupMethod"]
, orsnapshot.data!.data().get("signupMethod")
- (if you need the
id
of the document, it will be insnapshot.data!.id
)
In both cases you will get null
if the field does not exists, so you don't need containsKey
.
Important: make sure to check if snapshot.data!.exists
is true
, because Firestore will give you the document snapshot even if the data you are looking for can't be found. If exists
is true
, you are good to go with the above.