如何将Kotlin数据类对象转换为映射?

Gul*_*han 12 dictionary object kotlin

有没有简单的方法或任何标准的库方法来通过属性名称将Kotlin数据类对象转换为它的属性的地图/字典?可以避免反思吗?

Ken*_*ing 14

这个扩展函数使用反射,但也许它会帮助像我这样的人在未来遇到这个:

inline fun <reified T : Any> T.asMap() : Map<String, Any?> {
    val props = T::class.memberProperties.associateBy { it.name }
    return props.keys.associateWith { props[it]?.get(this) }
}
Run Code Online (Sandbox Code Playgroud)

  • 未解决的参考“memberProperties”。现在叫“会员” (5认同)
  • 很好的解决方案,尽管只是一个注释:这看起来不适用于嵌套数据结构。 (2认同)
  • 您有嵌套数据结构的解决方案吗? (2认同)

abg*_*UNG 10

我今天有相同的用例进行测试,最后我用Jackson对象映射器将Kotlin数据类转换为Map.在我的案例中,运行时性能不是一个大问题.我没有检查细节,但我相信它是在引擎盖下使用反射,但这是在幕后发生的事情.

例如,

val dataclass = DataClass(p1 = 1, p2 = 2)
val dataclassAsMap = objectMapper.convertValue(dataclass, object: 
TypeReference<Map<String, Any>>() {})

//expect dataclassAsMap == mapOf("p1" to 1, "p2" to 2)
Run Code Online (Sandbox Code Playgroud)


Col*_*ard 8

我使用的是jackson方法,但事实证明,此方法在Android上的首次序列化(在github问题上)非常糟糕。对于较旧的android版本,它的情况更糟,(请参阅此处的基准

但是使用Gson,您可以更快地完成此操作。双向转换如下所示:

val gson = Gson()

//convert a data class to a map
fun <T> T.serializeToMap(): Map<String, Any> {
    return convert()
}

//convert a map to a data class
inline fun <reified T> Map<String, Any>.toDataClass(): T {
    return convert()
}

//convert an object of type I to type O
inline fun <I, reified O> I.convert(): O {
    val json = gson.toJson(this)
    return gson.fromJson(json, object : TypeToken<O>() {}.type)
}
Run Code Online (Sandbox Code Playgroud)


Tim*_*gan 6

kotlinx.serialization有一个实验性的Properties格式,这使得将 Kotlin 类转换为映射变得非常简单,反之亦然:

@ExperimentalSerializationApi
@kotlinx.serialization.Serializable
data class Category constructor(
    val id: Int,
    val name: String,
    val icon: String,
    val numItems: Long
) {

    // the map representation of this class
    val asMap: Map<String, Any> by lazy { Properties.encodeToMap(this) }

    companion object {
        // factory to create Category from a map
        fun from(map: Map<String, Any>): Category =
            Properties.decodeFromMap(map)
    }
}
Run Code Online (Sandbox Code Playgroud)


ape*_*lla 4

您可以获得的最接近的是存储在映射中的委托属性

示例(来自链接):

class User(val map: Map<String, Any?>) {
    val name: String by map
    val age: Int     by map
}
Run Code Online (Sandbox Code Playgroud)

然而,将其与数据类一起使用可能效果不太好。

  • 他的问题是他想要相反的方式:将“数据类”转换为“Map&lt;String, Any?&gt;”。 (2认同)