簡體   English   中英

將 Map 轉換為數據 Class

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM