[英]Convert a Map to a Data Class
Kotlin 中是否有簡單的方法允許我將 Map 轉換為任意數據 class?
我正在嘗試轉換的 Map 具有數據 class 所需字段的所有鍵。
我四處尋找,但沒能找到任何似乎以非常通用的方式談論這樣做的東西。
我知道我可以使用ObjectMapper
,但這需要一個額外的庫。 尋找 Kotlin 可用的東西。
為什么不只使用地圖委托?
class MyData(val map: Map<String, String>) {
val foo by map
val bar by map
}
或者您可以使用伴隨對象包裝它並使用MyData.from(mymap)
調用它
data class MyData(val foo: String, val bar: String) {
companion object {
fun from(map: Map<String, String>) = object {
val foo by map
val bar by map
val data = MyData(foo, bar)
}.data
}
也許委托屬性適合您。 這樣你也可以只調整地圖。 然而,這也允許添加不能 1:1 映射到您的類屬性的鍵和值,例如:
class YourData {
val backedMap = mutableMapOf<String, String>()
var someProp by backedMap
}
val obj = YourData().apply {
someProp = "value"
}
現在,如果backedMap
可見,則還可以添加以下內容,即使不存在任何此類屬性:
obj.backedMap["unknown prop"] = "some other value"
另一方面,同樣的地圖可用於自動填寫您的字段:
val sourceMap = mutableMapOf("someProp" to "newValue") // the map you want to use to automatically fill up your data class
sourceMap.forEach { key, newValue -> obj.backedMap[key] = newValue }
另一種方法是“只是”使用反射。 這樣你就可以省略支持映射,而只是掃描屬性,例如:
YourData::class.memberProperties.asSequence()
.filterIsInstance<KMutableProperty<*>>()
.filter { it.name in sourceMap.keys }
.forEach { prop ->
prop.setter.call(obj, sourceMap[prop.name])
}
使用 kotlin 反射將構造函數參數映射到映射值,此通用函數適用於在主構造函數中接收字段數據的任何類
與 Firebase 等 JSON 數據庫配合良好,並使用 Firebase DocumentSnapshot.data 中的 Map 對象進行了測試
fun <T : Any> mapToObject(map: Map<String, Any>, clazz: KClass<T>) : T {
//Get default constructor
val constructor = clazz.constructors.first()
//Map constructor parameters to map values
val args = constructor
.parameters
.map { it to map.get(it.name) }
.toMap()
//return object from constructor call
return constructor.callBy(args)
}
有一些課
data class Person(val firs: String, val last: String)
像這樣使用
mapToObject(map, Person::class)
雖然這來晚了,但它可能會幫助像它這樣的人幫助我。
我查看了@killjoy 的評論,我立即感到震驚,因為我的誠實回答一直在我的腿上。
答:使用任何 Json 庫,例如 GSON() 或 JSon Kotlin 序列化庫,都可以解決這個問題。
這是一個通用示例:
allUploadsLiveData.observe(viewLifecycleOwner, {
val userUploads = ((it.value as HashMap<*, *>).values.toList())
for (upload in userUploads){
val product = ((upload as HashMap<*, *>).values.toList()[0] as HashMap<*, *>)
// Use Gson() to convert to Json format
val json = Gson().toJson(product)
try {
//Use Gson() to convert to Your custom class. For me here is ProductData
val data = Gson().fromJson(json, ProductData::class.java)
println("This is all the new data *********************************** ${data.productImageUrl}")
} catch (e: Exception){
println("Exception *************** $${e.printStackTrace()}")
}
}
})
不要忘記添加 Gson() 依賴項版本 2.9.0 是我此時回復的最新版本。 替換谷歌最多的版本 rest Gson
implementation "com.google.code.gson:gson:2.8.8"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.