将 kotlin kotlinx 序列化与泛型结合使用

问题描述 投票:0回答:1

大家好,我有以下代码,用于序列化为 json 字符串以存储在共享首选项中

interface Serializer {
  public fun <T> serialize(data: T, type: Class<T>): String
  public fun <T> deserialize(source: String, type: Class<T>): T?
}

我稍后可以创建此类的实现并使用 Moshi 序列化我的对象,如下所示

class SerializerImpl(
private val moshi: Moshi = Moshi.Builder()
    .build(),
) : Serializer {

override fun <T> deserialize(source: String, type: Class<T>): T? = try {
    moshi.adapter(type).fromJson(source)
} catch (exception: Exception) {
    null
}

override fun <T> serialize(data: T, type: Class<T>): String = 
   moshi.adapter(type).toJson(data)
}

您能否建议如何迁移此实现以使用 kotlinx 序列化,而不必更改 Serializer 接口的签名似乎我必须更改 Serializer 接口的类型以使用 KSerializer 才能使其正常工作,但我真的很想避免这种情况。

android kotlin json-deserialization moshi kotlinx.serialization
1个回答
0
投票

Kotlinx.serialization 为动态创建序列化器提供实验性支持,从提供的

Type
KType
:

class KotlinxSerializer : Serializer {
    override fun <T> serialize(data: T, type: Class<T>) = Json.encodeToString(type.serializer(), data)
    override fun <T> deserialize(source: String, type: Class<T>) = Json.decodeFromString(type.serializer(), source)
}

@OptIn(ExperimentalSerializationApi::class)
@Suppress("UNCHECKED_CAST")
private fun <T> Class<T>.serializer(): KSerializer<T> = Json.serializersModule.serializer(this) as KSerializer<T>

用途:

fun main() {
    val ser = KotlinxSerializer()
    val d1 = MyData("hello")
    val s = ser.serialize(d1, MyData::class.java)
    println(s) // {"foo":"hello"}
    val d2 = ser.deserialize(s, MyData::class.java)
    println(d2) // MyData(foo=hello)
}

@Serializable
data class MyData(val foo: String)

请注意,我们仍然需要用

@Serializable
标记所有数据类。如果没有这个,Kotlinx.serialization 就无法工作,因为这是一个编译时序列化框架。

© www.soinside.com 2019 - 2024. All rights reserved.