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