如何解决如何在使用 kotlinx.serialization 时为接口注册全局类型适配器,而不注释每个类?
Gson
会让我做一个 GsonBuilder().registerTypeAdapter(MyInterface::class.java,MyConcreteClassAdapter())
但我不能用 kotlinx.serialization
我只想公开接口 (ValueInterface
),所以我可以隐藏实现和序列化细节。但是,该接口是许多类的字段,例如 Box
,我不想通过使用 ValueInterface
@Serializable(with = SomeDeserializer::class)
字段来泄露序列化细节
请注意,ValueObject
具有自己的自定义序列化。
以下代码以 kotlinx.serialization.SerializationException: Class 'ValueObject' is not registered for polymorphic serialization in the scope of 'ValueInterface'. Mark the base class as 'sealed' or register the serializer explicitly.
中断。
但是,当我将 Box
值类型更改为 ValueObject
而不是 ValueInterface
时,它会起作用。
我需要更改什么才能使其像 Gson
一样工作并能够拥有 ValueInterface
类型的字段?
package kxs
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encodetoString
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import org.junit.Assert
import org.junit.Test
class KXSTest {
@Test
fun test(){
val actualStr = Json.encodetoString(Box("name1",ValueInterface.create(42)))
Assert.assertEquals("""{"name":"name1","value":42}""",actualStr)
val actualObj: Box = Json.decodeFromString("""{"name":"name2","value":43}""")
Assert.assertEquals(Box("name2",ValueInterface.create(43)),actualObj)
}
}
// public stuff
interface ValueInterface {
fun value() : Long
companion object {
fun create(long: Long) =
ValueObject(long)
}
}
@Serializable
data class Box(val name: String,val value: ValueInterface)
//internal details not meant to be exposed
@Serializable(with = ValueObjectAsLong::class)
data class ValueObject(val value: Long): ValueInterface {
init {
require(value > 0)
}
override fun value(): Long = value
}
object ValueObjectAsLong : KSerializer<ValueObject> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ValueObjectAsLong",PrimitiveKind.LONG)
override fun deserialize(decoder: Decoder): ValueObject {
return ValueObject(decoder.decodeLong())
}
override fun serialize(encoder: Encoder,value: ValueObject) {
encoder.encodeLong(value.value)
}
}
解决方法
要处理 ValueInterface
字段的序列化,只需将 @Serializable(with = ValueObjectAsLong::class)
注释从 ValueObject
类移动到 ValueInterface
。使用无参数 @Serializable
注释接口是不可能的,但是如果您为 with
参数提供一个值,它可以很好地编译:
@Serializable(with = ValueObjectAsLong::class)
interface ValueInterface { /*...*/ }
如果您需要序列化 3rd 方接口,这有点棘手。 首先,你需要为接口定义一个序列化器,而不是它的实现类:
object ValueInterfaceAsLong : KSerializer<ValueInterface> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ValueInterfaceAsLong",PrimitiveKind.LONG)
override fun serialize(encoder: Encoder,value: ValueInterface) = encoder.encodeLong(value.value())
override fun deserialize(decoder: Decoder) : ValueInterface = ValueObject(decoder.decodeLong())
}
然后将 @file:UseSerializers(ValueInterfaceAsLong::class)
注释添加到所有使用 ValueInterface
字段声明可序列化类的文件中。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。