Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sealed value class is serialized/deserialized incorrectly with default json polymorphism style #2938

Closed
Stream29 opened this issue Feb 27, 2025 · 5 comments

Comments

@Stream29
Copy link

Describe the bug
Value class that contains a primitive value cannot be serialized polymorphically with 'type' parameter.
The kotlinx.serialization-json library does not mention it and produces incorrect behaviour.

To Reproduce

@Serializable
sealed interface SealedInterface

@Serializable
@JvmInline
value class SealedValue(val value: Int) : SealedInterface

@Serializable
enum class SealedEnum : SealedInterface {
    A, B
}
        val json = Json {
            prettyPrint = true
            isLenient = true
            ignoreUnknownKeys = true
        }
        val valueClassInstance = SealedValue(1)
        val valueJson = json.encodeToString<SealedInterface>(valueClassInstance)
        println(valueJson)
        val deserializedValue = json.decodeFromString<SealedInterface>(valueJson)

This code outputs:

1

and then throw exception:

kotlinx.serialization.json.internal.JsonDecodingException: Expected JsonObject, but had JsonLiteral as the serialized body of SealedInterface at element: $
JSON input: 1
	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:400)
	at kotlinx.serialization.json.Json.decodeFromString(Json.kt:149)

Expected behavior

When facing the sealed value class that contains primitive type, a exception should be thrown directly, like the exception on sealed enum:

java.lang.IllegalStateException: Enums cannot be serialized polymorphically with 'type' parameter. You can use 'JsonBuilder.useArrayPolymorphism' instead
	at kotlinx.serialization.json.internal.PolymorphicKt.checkKind(Polymorphic.kt:71)
	at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:253)
	at kotlinx.serialization.json.internal.JsonStreamsKt.encodeByWriter(JsonStreams.kt:99)
	at kotlinx.serialization.json.Json.encodeToString(Json.kt:125)

Environment

  • Kotlin version: [2.1.0]
  • Library version: [1.8.0]
  • Kotlin platforms: [all]
@Stream29
Copy link
Author

Hello, I'd like to fix this issue.

@pdvrieze
Copy link
Contributor

@Stream29 To "fix" the issue, the question needs to be what the correct serialization form should be. Should it revert to the array form of polymorphism?

Stream29 added a commit to Stream29/kotlinx.serialization that referenced this issue Feb 27, 2025
…alized polymorphically with 'type' parameter

Associated issue: [issue-2938](Kotlin#2938)
Stream29 added a commit to Stream29/kotlinx.serialization that referenced this issue Feb 27, 2025
Stream29 added a commit to Stream29/kotlinx.serialization that referenced this issue Feb 27, 2025
…alized polymorphically with 'type' parameter

Associated issue: [issue-2938](Kotlin#2938)

(cherry picked from commit 71b38d9)
Stream29 added a commit to Stream29/kotlinx.serialization that referenced this issue Feb 27, 2025
Associated issue: [issue-2938](Kotlin#2938)

(cherry picked from commit d83fe73)
@Stream29
Copy link
Author

Stream29 commented Feb 27, 2025

Yes, so I add a error when serializing value class polymorphically.
PR
Now it works as expected, throwing exception whose message is Value class that contains primitive kind cannot be serialized polymorphically with 'type' parameter. You can use 'JsonBuilder.useArrayPolymorphism' instead

@sandwwraith
Copy link
Member

The decision to allow serialization of value class over primitive to (somewhat) incorrect form was deliberate: see #2049 (comment). Yes, we currently cannot deserialize such data back. We plan to address it systematically (as a part of #2835, most likely) rather than prohibiting writing such data completely. Besides, introducing such an exception would be a breaking change in the library.

@Stream29
Copy link
Author

Thank you for replying!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants