firebase-kotlin-sdk
firebase-kotlin-sdk copied to clipboard
Support Firestore Timestamps for all platforms
| Library | Class | Member | Platforms |
|---|---|---|---|
| Firestore (iOS) com.google.firebase (Android) |
FIRTimestamp (iOS) Timestamp (Android) |
N/A | All platforms |
There doesn't seem a way to reliably deserialise FIRTimestamp or com.google.firebase.Timestamp. Given this simple stub:
val o1 = NSMutableDictionary()
o1.setObject( FIRTimestamp(1, 2), forKey = "test" as NSString)
val o2 = decode(TestData.serializer(), o1)
print("@@@ $o2")
I've attempted to deserialise it with the decode function in dev.gitlive:firebase-common:
-
Decode as string
@Serializable data class TestData(val test: String) -
Decode as data class
@Serializable data class TestData(val test: TestTimestamp) @Serializable data class TestTimestamp(val seconds: Long, val nanoseconds: Int)
(1) works, but the resulting String is coming from -[NSObject description], which is not guaranteed to be a stable string representation. The format might also differ on different platforms.
(2) does not work, since it crashes when attempting to cast the ObjC FIRTimestamp object to a Map<*, *>.
Presumably this is the cause: https://github.com/GitLiveApp/firebase-kotlin-sdk/blob/master/firebase-common/src/iosMain/kotlin/dev/gitlive/firebase/_decoders.kt#L14
Given that
- (AFAIK)
FIRTimestamp(or its Android equivalent) is the only exception - how the decoder contract of
kotlinx.serializationis designed
So it seems it is a reasonable option to ad a special path for FIRTimestamp in the said code path, so as to enable (2).
I'd love to contribute on this, so please let me know if this makes sense.
Oh yes, I'm also very much interested this.
OK, yes we should probably support both decoding to a double/long and Timestamp class. For the Timestamp class we would need to create an expect class Timestamp to common layer
Happy to receive a PR on this @andersio
Probably should consider the kotlinx-datetime lib too.
We could make very good use of a fix to this issue, too. Experiencing the same problem.
OK, yes we should probably support both decoding to a double/long and Timestamp class. For the Timestamp class we would need to create an expect class Timestamp to common layer
I would love to contribute. Could you elaborate on that? Decoding and Encoding is implemented in firebase-common, wich firebase-firestore depends on. So how could we decode GeoPoint and Timestamp whose expect and actual classes are then defined in firebase-firestore?
@jonatbergn we would need to just wrap the native types received from the firebase SDKs with our expect/actual version. We would check the expected type during decode and assume we have the native type and wrap it.
Start by creating expect/actuals for GeoPoint and Timestamp in the same pattern we have for other classes
I was hoping to tackle this problem and after spending a few hours getting familiar with this library I'm not sure how to proceed.
It's my understanding that whatever we try to write gets sent through the serializer which breaks it down into primitives. The primitives are then encoded into lists and maps and passed to the native APIs.
It seems like any Timestamp class will be broken down into the primitives without any way to detect it at the encoding stage. I was thinking it could be possible to serialize it in a way that the encoder could rebuild it but this would require firebase-common to have knowledge of the Timestamp class and depend on firebase-firestore. The other option is to define the Timestamp class in the firebase-common package but this would make it depend on the firestore API.
I'm going to try the second approach as I don't care if it also depends on the firestore API as I already have that in my project.
EDIT: I realized even if I did this and managed to get it to write a Timestamp to firestore I have no idea how you'd decode one.
I now have a working version tested on Android only so far https://github.com/litclimbing/firebase-kotlin-sdk/tree/add-timestamp
My approach was to create specialized encoder/decoders and provide dummy serializers for the special types. The encoder/decoder look for the special types in the encode/decodeSerializableValue functions and does the translation there.
I also removed all the positive infinity double stuff used as a flag for the server timestamps. The FieldValues are recognized by the encoder and passed through.
Currently, I've only added support for firestore. The database module will need its own support added.
I believe this has been added in 1.9.0 - please reopen if something is missing