首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用kotlinx.serialization序列化Java路径

用kotlinx.serialization序列化Java路径
EN

Stack Overflow用户
提问于 2021-02-24 17:04:04
回答 1查看 1.4K关注 0票数 3

使用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也会抛出相同的错误。

是否有任何方法可以使路径正确地序列化/反序列化,而不必将其存储为字符串?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-05 11:53:33

Path是一个接口,因此它可以通过PolymorphicSerializer策略隐式序列化。这个策略要求您为实现它的子类注册序列化程序,但正如您所知,在这种情况下是不可能的。有一个默认多态序列化程序,但是它只影响反序列化过程,并且只有当反序列化值是JSONObject时才能工作。

和下面的序列化程序

代码语言:javascript
复制
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())
}
代码语言:javascript
复制
\\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 变量的序列化

在这种情况下,需要显式传递自定义序列化程序:

代码语言:javascript
复制
val path = Path.of("C:\\Temp")

val message1 = Json.encodeToString(PathAsStringSerializer, path).also { println(it) }
println(Json.decodeFromString(PathAsStringSerializer, message1))

类的序列化,它使用Path 作为泛型参数。

在这种情况下,您需要定义单独的序列化程序(您可以引用原始的PathAsStringSerializer)并显式地传递它们:

代码语言:javascript
复制
object ListOfPathsAsStringSerializer : KSerializer<List<Path>> by ListSerializer(PathAsStringSerializer)

val message2 = Json.encodeToString(ListOfPathsAsStringSerializer, listOf(path)).also { println(it) }
println(Json.decodeFromString(ListOfPathsAsStringSerializer, message2))
代码语言:javascript
复制
@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 = ...)注释:

代码语言:javascript
复制
@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>
)

或者仅仅是列出一次完整的文件

代码语言:javascript
复制
@file: UseSerializers(PathAsStringSerializer::class, ListOfPathsAsStringSerializer::class, BoxOfPathSerializer::class)

在这种情况下,插件生成的序列化程序就足够了:

代码语言:javascript
复制
val message4 = Json.encodeToString(InnerObject(mutableListOf(path), path, Box(path))).also { println(it) }
println(Json.decodeFromString<InnerObject>(message4))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66355506

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档