将 Firebase 数据快照反序列化为 Kotlin 数据 class
Deserialize a Firebase Data-Snapshot to a Kotlin data class
嗨,我有一个 Kotlin 数据 class 如下
data class User (
@get:Exclude val gUser: Boolean,
@get:Exclude val uid: String,
@get:PropertyName("display_name") val displayName: String,
@get:PropertyName("email") val email: String,
@get:PropertyName("account_picture_url") val accountPicUrl: String,
@get:PropertyName("provider") val provider: String
)
我可以毫无问题地序列化对象。但是我在进行 firebase 查询时无法反序列化对象。目前这就是我正在做的获取数据的工作
_firebaseReference.child(getString(R.string.firebase_users_key)).child(user.uid)
.setValue(user).addOnCompleteListener{
_firebaseReference.child("users").child(user.uid)
.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(p0: DataSnapshot) {
if (p0.exists()) {
val userHash = p0.value as HashMap<*, *>
var currentUser: User
if (userHash[getString(R.string.provider_key)]
!= getString(R.string.provider_google)) {
currentUser = User(false, p0.key!!,
userHash["display_name"].toString(),
userHash["email"].toString(),
userHash["account_picture_url"].toString(),
userHash["provider"].toString())
} else {
currentUser = User(true, p0.key!!,
userHash["display_name"].toString(),
userHash["email"].toString(),
userHash["account_picture_url"].toString(),
userHash["provider"].toString())
}
}
}
})
}
这只是我正在努力练习 Kotlin 的测试项目,但这是我想弄清楚的事情。
如果我做的完全错了请告诉我,任何建议将不胜感激
谢谢
Firebase 需要一个空构造函数才能反序列化对象:
data class User(
@Exclude val gUser: Boolean,
@Exclude val uid: String,
@PropertyName("display_name") val displayName: String,
@PropertyName("email") val email: String,
@PropertyName("account_picture_url") val accountPicUrl: String,
@PropertyName("provider") val provider: String
) {
constructor() : this(false, "", "", "", "", "")
}
您可以像这样声明它并提供ide一些默认值以便能够调用主构造函数,或者您可以为所有参数声明默认值:
data class User (
@Exclude val gUser: Boolean = false,
@Exclude val uid: String = "",
@PropertyName("display_name") val displayName: String = "",
@PropertyName("email") val email: String = "",
@PropertyName("account_picture_url") val accountPicUrl: String = "",
@PropertyName("provider") val provider: String = ""
)
然后将为您创建各种构造函数,包括一个空构造函数。
如果序列化出现问题,可能是因为 ide 生成的 getter 和 setter,请尝试使用 @get 和 @set 注释加强它们:
data class User (
@Exclude val gUser: Boolean = false,
@Exclude val uid: String = "",
@set:PropertyName("display_name")
@get:PropertyName("display_name")
var displayName: String = "",
@PropertyName("email") val email: String = "",
@set:PropertyName("account_picture_url")
@get:PropertyName("account_picture_url")
var accountPicUrl: String = "",
@PropertyName("provider") val provider: String = ""
)
在 Android Studio 中 (kotlin)
使用这个(仅 var 和 getter 和 setter):
- @set:PropertyName("email") @get:PropertyName("email") var emailPerson: String = ""
None 作品数:
- @PropertyName("email") var emailPerson: String = ""
- @PropertyName("email") val emailPerson: String = ""
- @get:PropertyName("email") val emailPerson: String = ""
Android Studio 4.1.2。 Gradle: com.google.firebase:firebase-数据库:19.6.0
我真正想要的是一个 Kotlin 数据 class ,它是从像这样的域模型接口派生的
data class Dto(@PropertyName("serialized_title") val override title: String) : DomainModel
在这种情况下,DomainModel 是这样定义的
interface DomainModel { val title: String }
我的目标是从 Firestore 获取数据并将反序列化的 Dto objects 提供给接收 objects 类型 DomainModel 的客户端。所以不幸的是,上面的这个解决方案没有奏效。我看到了使用 @get: 和 @set: 注释的解决方法,但我希望我的数据 class 属性是不可变的。在我的用例中,简单地使用 vars 是一个糟糕的设计决定。而且这个解决方案看起来很丑...
检查反编译后 Java-Code 我想到了这个解决方案
data class Dto(
@field:[JvmField PropertyName("serialized_title")]
override val title: String = "") : DomainModel
反编译后的 Java-Code 仅使用标题作为 public 具有 PropertyName 注释的最终字段。
我更喜欢这个解决方案,因为它不违反我做出的某些设计决定...
嗨,我有一个 Kotlin 数据 class 如下
data class User (
@get:Exclude val gUser: Boolean,
@get:Exclude val uid: String,
@get:PropertyName("display_name") val displayName: String,
@get:PropertyName("email") val email: String,
@get:PropertyName("account_picture_url") val accountPicUrl: String,
@get:PropertyName("provider") val provider: String
)
我可以毫无问题地序列化对象。但是我在进行 firebase 查询时无法反序列化对象。目前这就是我正在做的获取数据的工作
_firebaseReference.child(getString(R.string.firebase_users_key)).child(user.uid)
.setValue(user).addOnCompleteListener{
_firebaseReference.child("users").child(user.uid)
.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(p0: DataSnapshot) {
if (p0.exists()) {
val userHash = p0.value as HashMap<*, *>
var currentUser: User
if (userHash[getString(R.string.provider_key)]
!= getString(R.string.provider_google)) {
currentUser = User(false, p0.key!!,
userHash["display_name"].toString(),
userHash["email"].toString(),
userHash["account_picture_url"].toString(),
userHash["provider"].toString())
} else {
currentUser = User(true, p0.key!!,
userHash["display_name"].toString(),
userHash["email"].toString(),
userHash["account_picture_url"].toString(),
userHash["provider"].toString())
}
}
}
})
}
这只是我正在努力练习 Kotlin 的测试项目,但这是我想弄清楚的事情。
如果我做的完全错了请告诉我,任何建议将不胜感激
谢谢
Firebase 需要一个空构造函数才能反序列化对象:
data class User(
@Exclude val gUser: Boolean,
@Exclude val uid: String,
@PropertyName("display_name") val displayName: String,
@PropertyName("email") val email: String,
@PropertyName("account_picture_url") val accountPicUrl: String,
@PropertyName("provider") val provider: String
) {
constructor() : this(false, "", "", "", "", "")
}
您可以像这样声明它并提供ide一些默认值以便能够调用主构造函数,或者您可以为所有参数声明默认值:
data class User (
@Exclude val gUser: Boolean = false,
@Exclude val uid: String = "",
@PropertyName("display_name") val displayName: String = "",
@PropertyName("email") val email: String = "",
@PropertyName("account_picture_url") val accountPicUrl: String = "",
@PropertyName("provider") val provider: String = ""
)
然后将为您创建各种构造函数,包括一个空构造函数。
如果序列化出现问题,可能是因为 ide 生成的 getter 和 setter,请尝试使用 @get 和 @set 注释加强它们:
data class User (
@Exclude val gUser: Boolean = false,
@Exclude val uid: String = "",
@set:PropertyName("display_name")
@get:PropertyName("display_name")
var displayName: String = "",
@PropertyName("email") val email: String = "",
@set:PropertyName("account_picture_url")
@get:PropertyName("account_picture_url")
var accountPicUrl: String = "",
@PropertyName("provider") val provider: String = ""
)
在 Android Studio 中 (kotlin) 使用这个(仅 var 和 getter 和 setter):
- @set:PropertyName("email") @get:PropertyName("email") var emailPerson: String = ""
None 作品数:
- @PropertyName("email") var emailPerson: String = ""
- @PropertyName("email") val emailPerson: String = ""
- @get:PropertyName("email") val emailPerson: String = ""
Android Studio 4.1.2。 Gradle: com.google.firebase:firebase-数据库:19.6.0
我真正想要的是一个 Kotlin 数据 class ,它是从像这样的域模型接口派生的
data class Dto(@PropertyName("serialized_title") val override title: String) : DomainModel
在这种情况下,DomainModel 是这样定义的
interface DomainModel { val title: String }
我的目标是从 Firestore 获取数据并将反序列化的 Dto objects 提供给接收 objects 类型 DomainModel 的客户端。所以不幸的是,上面的这个解决方案没有奏效。我看到了使用 @get: 和 @set: 注释的解决方法,但我希望我的数据 class 属性是不可变的。在我的用例中,简单地使用 vars 是一个糟糕的设计决定。而且这个解决方案看起来很丑...
检查反编译后 Java-Code 我想到了这个解决方案
data class Dto(
@field:[JvmField PropertyName("serialized_title")]
override val title: String = "") : DomainModel
反编译后的 Java-Code 仅使用标题作为 public 具有 PropertyName 注释的最终字段。
我更喜欢这个解决方案,因为它不违反我做出的某些设计决定...