使用kotlinx.serialization时,这段代码将引发一个错误:println(Json.encodeToString(Path.of("value")))说kotlinx.serialization.SerializationException: Class 'WindowsPath' is not registered for polymorphic serialization in the scope of 'Path'.
WindowsPath是内部的,因此我不能将它注册为多态子类(就像在这个例子中那样),只使用Path本身,甚至用于Path的自定义KSerializer也会抛出相同的错误。
是否有任何方法可以使路径正确地序列化/反序列化,而不必将其存储为字符串?
发布于 2021-03-05 11:53:33
Path是一个接口,因此它可以通过PolymorphicSerializer策略隐式序列化。这个策略要求您为实现它的子类注册序列化程序,但正如您所知,在这种情况下是不可能的。有一个默认多态序列化程序,但是它只影响反序列化过程,并且只有当反序列化值是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))类的序列化,它使用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>
)或者仅仅是列出一次完整的文件
@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))https://stackoverflow.com/questions/66355506
复制相似问题