英文:
Serialization with sealed classes fails in Kotlin serialization
问题
在以下用例中,我在使用Kotlin序列化时遇到了问题:
@Serializable
sealed class NetworkAnswer {
@SerialName("answerId")
abstract val id: Int
}
@Serializable
data class NetworkYesNoAnswer(
override val id: Int,
@SerialName("isPositive")
val isPositive: Boolean
) : NetworkAnswer()
当我序列化时:
val json = Json { ignoreUnknownKeys = true; explicitNulls = false }
val result: NetworkYesNoAnswer = json.decodeFromString(NetworkYesNoAnswer.serializer(), """
{
"answerId": 1,
"isPositive": true
}
""".trimIndent()
)
我遇到了以下错误:
Caused by: kotlinx.serialization.MissingFieldException: Fields [id] are required for type with serial name 'NetworkYesNoAnswer', but they were missing
唯一让序列化正常工作的方法是,如果我同时使用成员名和"SerialName"相同的名称,如下所示:
@Serializable
sealed class NetworkAnswer {
@SerialName("answerId")
abstract val answerId: Int
}
@Serializable
data class NetworkYesNoAnswer(
override val answerId: Int,
@SerialName("isPositive")
val isPositive: Boolean
) : NetworkAnswer()
这有点违背了"SerialName"的目的,有没有一种方法可以解决这个问题,而不必使用相同的名称?
英文:
I'm having trouble with kotlin-serialization in the following use case:
@Serializable
sealed class NetworkAnswer {
@SerialName("answerId")
abstract val id: Int
}
@Serializable
data class NetworkYesNoAnswer(
override val id: Int,
@SerialName("isPositive")
val isPositive: Boolean
) : NetworkAnswer()
When I serialize this:
val json = Json { ignoreUnknownKeys = true; explicitNulls = false }
val result: NetworkYesNoAnswer = json.decodeFromString(NetworkYesNoAnswer.serializer(), """
{
"answerId": 1,
"isPositive": true
}
""".trimIndent()
)
I get the following error
Caused by: kotlinx.serialization.MissingFieldException: Fields [id] are required for type with serial name 'NetworkYesNoAnswer', but they were missing
The only way the serialization works is if I use the same name for both the member and "SerialName", like so:
@Serializable
sealed class NetworkAnswer {
@SerialName("answerId")
abstract val answerId: Int
}
@Serializable
data class NetworkYesNoAnswer(
override val answerId: Int,
@SerialName("isPositive")
val isPositive: Boolean
) : NetworkAnswer()
This kinda defeats the purpose of "SerialName", is there a way to solve that without using the same name?
答案1
得分: 1
在基类上声明@SerialName
对于子类覆盖的成员声明没有影响。
相反,您可以在子类上声明@SerialName
。无需更改字段的实际名称。
@Serializable
data class NetworkYesNoAnswer(
@SerialName("answerId")
override val id: Int,
@SerialName("isPositive")
val isPositive: Boolean
) : NetworkAnswer()
目前似乎不支持在基类上声明@SerialName
并将其应用于所有子类,但社区中的其他成员也希望支持此功能,例如GitHub上的这里。
OT:很可能您可以使用sealed interface
,它首次在Kotlin v1.5.0中引入,而不是使用sealed class
。
英文:
Declaring a @SerialName
on a base class has no effect on member declarations overridden by child classes.
Instead, you can declare @SerialName
on the child class instead. There is no need to change the actual name of the field.
@Serializable
data class NetworkYesNoAnswer(
@SerialName("answerId")
override val id: Int,
@SerialName("isPositive")
val isPositive: Boolean
) : NetworkAnswer()
Declaring the @SerialName
on the base class and applying it to all children seems NOT to be supported as of now, but is desired by other members of the community as well, e.g. here on GitHub.
OT: Most likely you could use a sealed interface
, which was first introduced in Kotlin v1.5.0, instead of a sealed class
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论