I have a Kotlin data class that effortlessly adds a Firestore server upload timestamp to an object when it’s saved as a document to the Firestore database in the cloud.
All I have to do is add a FieldValue
property to the Kotlin data class in the Android client, complete with the default value FieldValue.serverTimestamp()
, and the object serializes to a Firestore document with the correct upload timestamp without any more effort from me:
data class CloudEntity(
val uu: String = "",
val de: String = "",
...
val cr: Long = 0L,
val ts: FieldValue = FieldValue.serverTimestamp() //server timestamp
)
But when I try to deserialize that Firestore document back to that exact same data class, using something like documentChange.document.toObject<CloudEntity>()
, I get the error No properties to serialize found on class com.google.firebase.firestore.FieldValue
.
So how do I deserialize that timestamp property?
I don’t actually need that timestamp value on the client (it’s only used in server-side queries), so I’d also be happy to implement a solution that doesn’t actually deserialize the server timestamp value but simply discards the value and returns a zero value or something. Just as long as it doesn’t crash the whole deserialization.
2
Answers
I suggest you to create a separate object to retrieve from cloud but without that field! Something like this:
FieldValue.serverTimestamp() just returns a sentinel object that you use when writing a field to a document. It indicates the server should replace it with an actual Timestamp object. serverTimestamp() itself does not contain any date information, and you can’t convert it to a date.
When you write the sentinel value to a document, and read it back out, it will become a Timestamp type object, which you can convert to a native Date object with its toDate() method, if you want to. You could add a ‘val ts: Date’ into the Entity class I wrote before, and then retrieve that value.
If you don’t want to create that separate Entity without that field, you could remove that field from your CloudEntity class and add that field as an update to the document in your ‘write’ method.
While Matilveiro’s solution might work, please note that isn’t quite necessary. If you want to have a Timestamp type field inside your
CloudEntity
class, the simplest solution in Kotlin would be to define thets
field to be of type Date and use an annotation like this:There is no need to initialize the field in any way. So when you create an object of the
CloudEntity
class you don’t have to pass anything to the constructor. Firebase servers will read yourts
field, as it is a ServerTimestamp (see the annotation), and it will populate that field accordingly.On the other hand, if you have used a Map, then indeed you had to pass
FieldValue.serverTimestamp()
as value:So it’s one or the other.