Rap*_*ita 5 generics json kotlin kotlin-reified-type-parameters kotlinx.serialization
实际上,主要问题仍然是 Kotlin 中的类没有具体化的类型参数。但这就是为什么在这个特定情况下这让我感到困扰:
假设您有一个包装类Wrapper
,它接受一个字符串content
和一个类* ,并且可以通过调用函数按需解析为 JSON 来输出检索到的type
类的对象:type
content
getObj()
class Wrapper<T>(private val content: String, /*private val type: KClass<*>*/) {
fun getObj(): T {
// ?
}
}
Run Code Online (Sandbox Code Playgroud)
我想使用 kotlinx.serialization。现在,你可能已经注意到我之前是如何在“class”后面加星号的。原因是:是的,Wrapper
必须以某种方式参加目标课程,但是如何呢?它应该只是 typearg (不起作用,因为类型erausre)还是引用KClass
(不起作用,因为我需要具体化的 typearg)?
事实是,据我所知,将通用 JSON 解码为可序列化目标类的唯一方法是使用Json.decodeFromString<T>(content)
,其中T
是目标类型,content
是 JSON 字符串。现在,T
被定义为具体化(以便可以在运行时处理类型)并且只能用另一个具体化的 typearg 或实际的类引用来填充。我无法使用另一个具体化的类型参数,因为我处于类的上下文中,并且类不能具有具体化的类型参数。我也不能使用实际的类引用,因为类的用户应该能够使用不同的目标来构造它,例如他们决定目标是什么,而不是我。
那么,我该如何使用 kotlinx.serialization 来做到这一点?有可能吗?
好吧,还没人回答这个问题,但我也在 r/Kotlin subreddit 中发布了这个问题。这里是。
我实际上在那里得到了答案(归功于 u/JakeWharton),并且由于您可能会遇到这个 StackOverflow 问题,因为您在 google 上搜索了相同的问题,因此您可能会很高兴在这里找到答案。所以这是我尝试解释的答案:
所以,基本上,kotlinx-serialization 确实不适用于KClass
es。但当你考虑一下时,你只需要KClass
确定如何序列化它。由于这是在使用 KXS 时在编译时确定的,因此您实际上只需要传递序列化器(定义如何序列化/反序列化类的实际策略)。您可以@Serializable
通过调用.serializer()
它来为每个带有注释的类获取序列化器;结果将是类型KSerializer<T>
. 所以,而不是有
class Wrapper<T>(private val content: String, private val type: KClass<T>)
Run Code Online (Sandbox Code Playgroud)
并通过构建它
val wrapper = Wrapper("{}", Foo::class)
Run Code Online (Sandbox Code Playgroud)
你可以这样做:
class Wrapper<T>(private val content: String, private val serializer: KSerializer<T>)
Run Code Online (Sandbox Code Playgroud)
然后像这样构造它:
val wrapper = Wrapper("{}", Foo.serializer())
Run Code Online (Sandbox Code Playgroud)
(假设Foo
用 注释@Serializable
)
然后,您可以使用KSerializer
代替 typearg 来序列化和反序列化,如下所示:
val obj: T = Json.decodeFromString(serializer, "[Your JSON String]")
val str: String = Json.encodeToString(serializer, obj)
Run Code Online (Sandbox Code Playgroud)
就是这样!只需更换您的常规(K)Class
方法,KSerializer
它就可以与 KXS 一起使用。
归档时间: |
|
查看次数: |
2029 次 |
最近记录: |