I am developing an Android application using Firebase Realtime Database.
According to Firebase document,
Pass a custom Java object, if the class that defines it has a default constructor that takes no arguments and has public getters for the properties to be assigned.
So I made a custom Kotlin data class with Instant
field as below :
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
@Serializable
data class UserStatus(
// ...
val updatedAt: Instant = Clock.System.now(),
// ...
}
It has default constructor and only public getters.
val newUserStatus = UserStatus()
Firebase.database.reference.child(REFERENCE_USER_STATUS_NAME).child(createdUser.uid).setValue(newUserStatus).await()
But, because of Instant
field of the class, the error occurs as below :
com.google.firebase.database.DatabaseException: Invalid key: value$kotlinx_datetime. Keys must not contain '/', '.', '#', '$', '[', or ']'
at com.google.firebase.database.core.utilities.Validation.validateWritableKey(Validation.java:123)
at com.google.firebase.database.core.utilities.Validation.validateWritableObject(Validation.java:106)
at com.google.firebase.database.core.utilities.Validation.validateWritableObject(Validation.java:107)
at com.google.firebase.database.DatabaseReference.setValueInternal(DatabaseReference.java:283)
at com.google.firebase.database.DatabaseReference.setValue(DatabaseReference.java:159)
//...
When I comment that Instant
field and build, It works well.
What am I missing?
Instant
has a default serializer.
I figured out that Firebase uses an internal property of kotlinx.datetime.Instant
so the key includes $
.
When I asked the same question on kotlinx.datetime
repository, the maintainer answered me he thinks this problem is related to the Firebase, not Instant
.link
2
Answers
The question is, why? You have to understand that you are trying to save a complex Instant object which is obviously not compatible with the RealTimeDatabase saving standard. According to the documentation, you should simplify the database structure as much as possible.
or
Wouldn’t it be less expensive?
-Hugs
As you already noticed, the error that you get is because of the following line of code:
And this is because now() returns an object of type Instant. Even if such a field has a default serializer and also exists in a class that is Serializable, it will always produce an error because such an object is not a supported data type.
While kllysmman’s solution might work, as it will save a long value in the database, it will more elegant to save the date and time in the Realtime Database as a
timestamp
. To achieve that, please check my answer in the following post: