Path 是一个接口,因此它可以通过 PolymorphicSerializer 策略隐式序列化。此策略要求您为实现它的子类注册序列化程序,但如您所知,在这种情况下这是不可能的。
有一个default polymorphic serializer,但它只影响反序列化过程,并且只有在可反序列化的值为JSONObject时才有效。
对于下面的序列化器
object PathAsStringSerializer : KSerializer<Path> {
override val descriptor = PrimitiveSerialDescriptor("Path", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Path) = encoder.encodeString(value.toAbsolutePath().toString())
override fun deserialize(decoder: Decoder): Path = Path.of(decoder.decodeString())
}
\\Not working
val module = SerializersModule { polymorphicDefault(Path::class) { PathAsStringSerializer } }
val decoded : Path = Json { serializersModule = module }.decodeFromString("C:\\Temp")
它会抛出运行时异常kotlinx.serialization.json.internal.JsonDecodingException: Expected class kotlinx.serialization.json.JsonObject as the serialized body of kotlinx.serialization.Polymorphic<Path>, but had class kotlinx.serialization.json.JsonLiteral
所以,不能用普通的方式序列化,它的序列化/反序列化有3种情况,需要处理:
1。简单Path变量的序列化
在这种情况下,您需要显式传递您的自定义序列化程序:
val path = Path.of("C:\\Temp")
val message1 = Json.encodeToString(PathAsStringSerializer, path).also { println(it) }
println(Json.decodeFromString(PathAsStringSerializer, message1))
2。类的序列化,使用Path 作为泛型参数
在这种情况下,您需要定义单独的序列化程序(您可以参考原始的PathAsStringSerializer)并显式传递它们:
object ListOfPathsAsStringSerializer : KSerializer<List<Path>> by ListSerializer(PathAsStringSerializer)
val message2 = Json.encodeToString(ListOfPathsAsStringSerializer, listOf(path)).also { println(it) }
println(Json.decodeFromString(ListOfPathsAsStringSerializer, message2))
@Serializable
data class Box<T>(val item: T)
object BoxOfPathSerializer : KSerializer<Box<Path>> by Box.serializer(PathAsStringSerializer)
val message3 = Json.encodeToString(BoxOfPathSerializer, Box(path)).also { println(it) }
println(Json.decodeFromString(BoxOfPathSerializer, message3))
3。具有上述类型字段的类的序列化
在这种情况下,您需要为这些字段添加尊重的@Serializable(with = ...) 注释:
@Serializable
data class InnerObject(
@Serializable(with = ListOfPathsAsStringSerializer::class)
val list: MutableList<Path> = mutableListOf(),
@Serializable(with = PathAsStringSerializer::class)
val path: Path,
@Serializable(with = BoxOfPathSerializer::class)
val box: Box<Path>
)
或者只是list them once for a whole file:
@file: UseSerializers(PathAsStringSerializer::class, ListOfPathsAsStringSerializer::class, BoxOfPathSerializer::class)
这种情况下插件生成的序列化器就足够了:
val message4 = Json.encodeToString(InnerObject(mutableListOf(path), path, Box(path))).also { println(it) }
println(Json.decodeFromString<InnerObject>(message4))