Gson
允许我执行GsonBuilder().registerTypeAdapter(MyInterface::class.java, MyConcreteClassAdapter())
,但我无法对kotlinx.serialization
执行相同操作
我只想公开接口(ValueInterface
),这样我就可以隐藏实现和序列化细节。
请注意,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)
}
}
1条答案
按热度按时间gv8xihay1#
要处理
ValueInterface
字段的序列化,只需将@Serializable(with = ValueObjectAsLong::class)
注解从ValueObject
类移到ValueInterface
。使用无参数@Serializable
注解接口是不可能的,但如果您为with
参数提供一个值,它将编译得很好:如果你需要序列化第三方接口,这就有点麻烦了。首先,你需要为接口定义一个序列化器,而不是它的实现类:
然后使用
ValueInterface
字段将@file:UseSerializers(ValueInterfaceAsLong::class)
注解添加到所有声明了可序列化类的文件中。