-
Notifications
You must be signed in to change notification settings - Fork 60
Description
Hi,
As I working with firestore plugin for the MAUI project, I encountered some issues dealing with the map within the document.
I did a testing of a simple document with map fields as below

For the common data type as the map value I am using (string, number, boolean and DateTimeOffset), I have no issue to create a class which implements IFirestoreObject and set them to cloud Firestore on Android platform.
public class DataClassWithMaps : IFirestoreObject
{
[FirestoreProperty(nameof(StringMaps))]
public Dictionary<string, string> StringMaps { get; set; } = new Dictionary<string, string>();
[FirestoreProperty(nameof(NumberMaps))]
public Dictionary<string, double> NumberMaps { get; set; } = new Dictionary<string, double>();
[FirestoreProperty(nameof(BooleanMaps))]
public Dictionary<string, bool> BooleanMaps { get; set; } = new Dictionary<string, bool>();
[FirestoreProperty(nameof(DateMaps))]
public Dictionary<string, DateTimeOffset> DateMaps { get; set; } = new Dictionary<string, DateTimeOffset>();
}
However on Android, I encounter issue getting/retrieving the data.
No exception when calling doc.GetDocumentSnapshotAsync(), however exception occurred when attempt to access IDocumentSnapshot.Data when the class contains Dictionary<string, DateTimeOffset> OR Dictionary<string, bool> property, with the exception below
System.ArgumentException: 'Could not convert object of type Java.Lang.Boolean to Java.Lang.Object. Does it extend IFirestoreObject?'
System.ArgumentException: 'Could not convert object of type Firebase.Timestamp to Java.Lang.Object. Does it extend IFirestoreObject?'
On iOS, the condition is kind of different.
Exception happen on iOS by just calling doc.SetDataAsync to store the data to the cloud Firestore if Dictionary<string, DateTimeOffset> contain data in the class.
Exception has occurred: CLR/System.ArgumentException
An unhandled exception of type 'System.ArgumentException' occurred in Microsoft.iOS.dll: 'Couldn't put object of type System.DateTimeOffset into NSDictionary'
at ObjCRuntime.Runtime.ThrowException(IntPtr gchandle)
at UIKit.UIApplication.UIApplicationMain(Int32 argc, String[] argv, IntPtr principalClassName, IntPtr delegateClassName)
at UIKit.UIApplication.Main(String[] args, Type principalClass, Type delegateClass)
However, unlike Android. iOS platform has no issue getting the document with these maps.
In summary,
Android has no issue set the document
iOS has no issue get the document
Android cannot get the document (.Data) if the document contains Dictionary<string, bool> OR Dictionary<string, DateTimeOffset>
iOS cannot set the document if the document contains Dictionary<string, DateTimeOffset>
Below is the sample code for further testing and investigation, may comment out part of the code to test the behavior.
Thank you.
async Task ExcuteTestGetDataWithMap()
{
var db = CrossFirebaseFirestore.Current;
DateTimeOffset dt = DateTimeOffset.Now;
var doc = db.GetCollection("zzz").GetDocument("docWithMaps");
var data = new DataClassWithMaps();
data.StringMaps.Add("Key1", "Hello World"); // both working
data.StringMaps.Add("Key2", "Hello Universe");
data.NumberMaps.Add("Key1", 999.99); // both working
data.NumberMaps.Add("Key2", -999.99);
data.BooleanMaps.Add("Key1", true); // Android can set cannot get, iOS Working
data.BooleanMaps.Add("Key2", false);
data.DateMaps.Add("Key1", dt); // Android can set cannot get, iOS cannot set can get
data.DateMaps.Add("Key2", DateTimeOffset.Now);
await doc.SetDataAsync(data, SetOptions.Merge());
var snapshot = await doc.GetDocumentSnapshotAsync<DataClassWithMaps>();
if (snapshot?.Data != null)
{
var dataOutput = snapshot.Data;
if (dataOutput.StringMaps.TryGetValue("Key1", out string? stringValue))
Debug.WriteLine(stringValue ?? "");
if (dataOutput.NumberMaps.TryGetValue("Key1", out double numberValue))
Debug.WriteLine(numberValue);
if (dataOutput.BooleanMaps.TryGetValue("Key1", out bool booleanValue))
Debug.WriteLine(booleanValue);
if (dataOutput.DateMaps.TryGetValue("Key1", out DateTimeOffset dtoValue))
Debug.WriteLine(dtoValue.ToString());
}
}