kotlin 如何在Android中反序列化Firestore FieldValues?

vwhgwdsa  于 2022-12-13  发布在  Kotlin
关注(0)|答案(2)|浏览(126)

我有一个Kotlin数据类,当对象作为文档保存到云中的Firestore数据库时,它可以毫不费力地向对象添加Firestore服务器上载时间戳。
我所要做的就是在Android客户端中向Kotlin数据类添加一个FieldValue属性,并使用默认值FieldValue.serverTimestamp()完成,然后该对象将序列化为一个Firestore文档,并带有正确的上传时间戳,而无需我再做任何工作:

data class CloudEntity(
  val uu: String = "",
  val de: String = "",
  ...
  val cr: Long = 0L,
  val ts: FieldValue = FieldValue.serverTimestamp() //server timestamp
)

但是,当我尝试使用类似documentChange.document.toObject<CloudEntity>()的代码将Firestore文档反序列化回完全相同的数据类时,我得到了错误No properties to serialize found on class com.google.firebase.firestore.FieldValue
那么,如何反序列化时间戳属性呢?
我实际上并不需要客户机上的时间戳值(它只用于服务器端查询),所以我也很乐意实现一个解决方案,该解决方案实际上并不反序列化服务器时间戳值,而是简单地丢弃该值并返回零值或其他值。只要它不使整个反序列化崩溃即可。

c9x0cxw0

c9x0cxw01#

我建议你创建一个单独的对象来从云中检索,但是不要那个字段!类似这样:

data class CloudEntity(
    val uu: String = "",
    val de: String = "",
    val cr: Long = 0L,
    val ts: FieldValue = FieldValue.serverTimestamp() //server timestamp
)

// Domain entity
data class Entity(
    val uu: String = "",
    val de: String = "",
    val cr: Long = 0L
)

// Mapper from domain to cloud
fun Entity.toCloud() = CloudEntity(uu, de, cr)

serverTimestamp()只返回一个在将字段写入文档时使用的标记对象。它指示服务器应该将其替换为实际的Timestamp对象。serverTimestamp()本身不包含任何日期信息,并且不能将其转换为日期。
当您将sentinel值写入文档,然后再将其读取出来时,它将成为一个Timestamp类型的对象,如果需要,您可以使用它的toDate()方法将其转换为本机Date对象。您可以添加一个'val ts:Date'插入到我以前写的Entity类中,然后检索那个值。
如果您不想创建没有该字段的单独实体,您可以从CloudEntity类中删除该字段,并在“write”方法中将该字段作为更新添加到文档中。

czq61nw1

czq61nw12#

虽然Matilveiro的解决方案可能有效,但请注意,这并不是必须的。如果您希望在CloudEntity类中有一个Timestamp类型的字段,Kotlin中最简单的解决方案是将ts字段定义为Date类型,并使用如下注解:

@ServerTimestamp
var ts: Date? = null

不需要以任何方式初始化该字段。因此,当你创建CloudEntity类的对象时,你不需要向构造函数传递任何东西。Firebase服务器将读取你的ts字段,因为它是一个ServerTimestamp(见注解),并相应地填充该字段。
另一方面,如果你使用了Map,那么你确实必须传递FieldValue.serverTimestamp()作为值:

val cloudEntry = mapOf(
    "ts" to FieldValue.serverTimestamp(),
    //Other fields.
)

所以这是一个或其他。

相关问题