如何使用 Kotlin 序列化来序列化 Any?

问题描述 投票:0回答:1

如何序列化以下数据?这是

AppConfig
value 的值可以是任何类型,我不能使用 Any 进行序列化。

[
 {
    "key": "PROFILE_PHOTO",
    "value": "url"
  },
  {
    "key": "RELATIONSHIP",
    "value": 0.6
  },
  {
    "key": "SEX",
    "value": [ "Man", "Woman"]
  },
  {
    "key": "IOS_VER",
    "value": 5
  }
]
kotlin serialization kotlinx.serialization
1个回答
0
投票

多态性就是答案

简短的答案是:具有多态性。我们需要不同的类型来表示可以接收的不同类型的对象。

在很大程度上,类型的选择取决于对象的含义和用途,而不仅仅是像我们这里一样查看原始数据。

但是,我们可以根据您提供的内容猜测合适的类型。

密封的类层次结构

现在我们要编写一个密封类层次结构来表示传入的对象,因为这使得多态序列化变得简单(docs):

@Serializable
@JsonClassDiscriminator("key")
sealed class ApiObject

@Serializable @SerialName("PROFILE_PHOTO")
data class ProfilePhoto(@SerialName("value") val url: String) : ApiObject()

@Serializable @SerialName("RELATIONSHIP")
data class Relationship(@SerialName("value") val coefficient: Double) : ApiObject()

@Serializable @SerialName("SEX")
data class Sex(@SerialName("value") val sexes: List<SexType>) : ApiObject()

@Serializable @SerialName("IOS_VER")
data class IosVersion(@SerialName("value") val versionNumber: Int) : ApiObject()

enum class SexType { Man, Woman }

我们还使用了该库的一些功能来为我们提供更可用的类层次结构。特别是:

  • 我们已经为我们可以从 API 接收的每种可能的消息类型指定了名称,并且我们使用

    SerialName
    注释为传入的“值”字段提供了有意义的名称。

  • “关键”字段将用作我们的“鉴别器”,它告诉库要选择哪一个类。默认情况下,这是“type”字段,因此我们需要告诉库使用“key”而不是

    JsonClassDiscriminator
    注释。

  • 最后,因为“关键”字段是在 screaming Snake case 中给出的,所以我们需要使用

    SerialName
    注解来调整类的序列化名称,以便我们的类名称能够符合习惯的 Kotlin 实践。

测试代码

现在我们准备好测试我们的代码了:

val testMessage: String = """
[
 {
    "key": "PROFILE_PHOTO",
    "value": "url"
  },
  {
    "key": "RELATIONSHIP",
    "value": 0.6
  },
  {
    "key": "SEX",
    "value": [ "Man", "Woman"]
  },
  {
    "key": "IOS_VER",
    "value": 5
  }
]
"""
val deserializedMessage: List<ApiObject> = Json.decodeFromString(testMessage)

val expectedDeserializedMessage = listOf(
    ProfilePhoto("url"),
    Relationship(0.6),
    Sex(listOf(SexType.Man, SexType.Woman)),
    IosVersion(5)
)
println("Does our code work? ${expectedDeserializedMessage == deserializedMessage}")
© www.soinside.com 2019 - 2024. All rights reserved.