@Polymorphic annotation does not work for properties when used on type
See original GitHub issueDescribe the bug
I have a class hierarchy with several inheritance hierarchies. In this hierarchy, members marked as Polymorphic do not work.
To Reproduce
Here is a test:
import kotlinx.serialization.Polymorphic
import kotlinx.serialization.PolymorphicSerializer
import kotlin.test.Test
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import kotlin.test.assertEquals
@Serializable
sealed class Fruit
@Serializable
data class Banana(val name: String) : Fruit()
@Serializable
data class Apple(val id: Int) : Fruit()
@Serializable
sealed class Box
@Serializable
data class SmallBox(val content: @Polymorphic Fruit): Box()
@Serializable
data class LargeBox(val content: List<@Polymorphic Fruit>): Box()
class Test {
@Test
fun test() {
val format = Json(context= SerializersModule {
polymorphic(Fruit::class) {
Banana::class with Banana.serializer()
Apple::class with Apple.serializer()
}
polymorphic(Box::class) {
SmallBox::class with SmallBox.serializer()
LargeBox::class with LargeBox.serializer()
}
})
val data = SmallBox(Banana("Test"))
// val data = LargeBox(listOf(Banana("Test"), Apple(22)))
val asString = format.stringify(PolymorphicSerializer(Box::class), data)
println(asString)
val obj = format.parse(PolymorphicSerializer(Box::class), asString)
assertEquals(data, obj)
}
}
The printout is
{"type":"SmallBox","content":{}}
And the test fails with
java.lang.InstantiationError: Fruit
at Fruit$$serializer.deserialize(BugTest.kt)
at Fruit$$serializer.deserialize(BugTest.kt:10)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:33)
at kotlinx.serialization.json.internal.AbstractJsonTreeInput.decodeSerializableValue(TreeJsonInput.kt:48)
at kotlinx.serialization.TaggedDecoder$decodeSerializableElement$1.invoke(Tagged.kt:257)
at kotlinx.serialization.TaggedDecoder.tagBlock(Tagged.kt:270)
at kotlinx.serialization.TaggedDecoder.decodeSerializableElement(Tagged.kt:257)
at SmallBox$$serializer.deserialize(BugTest.kt)
at SmallBox$$serializer.deserialize(BugTest.kt:21)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:33)
at kotlinx.serialization.json.internal.AbstractJsonTreeInput.decodeSerializableValue(TreeJsonInput.kt:48)
at kotlinx.serialization.CoreKt.decode(Core.kt:79)
at kotlinx.serialization.json.internal.TreeJsonInputKt.readJson(TreeJsonInput.kt:27)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:41)
at kotlinx.serialization.json.internal.StreamingJsonInput.decodeSerializableValue(StreamingJsonInput.kt:29)
at kotlinx.serialization.CoreKt.decode(Core.kt:79)
at kotlinx.serialization.json.Json.parse(Json.kt:148)
at BugTest.test(BugTest.kt:45)
When I use the line with LargeBox instead of the SmallBox line, so, polymorphic elements in a list, it works as expected.
Expected behavior
The printout should be
{"type":"SmallBox","content":{"type":"Banana","name":"Test"}}
Environment
- Kotlin version: 1.3.30
- Library version: 0.11.0
- Kotlin platforms: JVM, I did not try other platforms
- Gradle version: 5.2.1
- JVM: 1.8.0_201 (Oracle Corporation 25.201-b09)
- OS: Linux 4.20.6-200.fc29.x86_64 amd64
Issue Analytics
- State:
- Created 4 years ago
- Comments:5 (2 by maintainers)
Top Results From Across the Web
Why does Jackson polymorphic serialization not work in lists?
(or "@class" or whatever your type field is named) Jackson will serialize it regardless of where the object is located.
Read more >Polymorphic resolution without annotations, looking for ...
Hey there, I am currently trying to handle polymorphic resolution without using the annotations and unfortunately, I haven't found any completely working ......
Read more >JsonUnwrapped (Jackson-annotations 2.13.0 API) - FasterXML
Annotation can only be added to properties, and not classes, as it is contextual. When values are deserialized "wrapping" is applied so that...
Read more >Inheritance in Jackson | Baeldung
This tutorial will demonstrate how to handle inclusion of subtype metadata and ignoring properties inherited from superclasses with Jackson.
Read more >Inheritance and Polymorphism - Swagger
It is recommended to avoid using conflicting properties (like properties that have the same names, but different data types).
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@danielebart Yes, registering is now necessary, since polymorphic serialization is now multiplatform and JS and Native lack a necessary amount of reflection (like
Class.forName
) to retrieve serializers without registering.Regarding sealed classes, we have plans to improve their polymorphic serialization (since all their inheritors indeed are known in compile-time and therefore can be registered automatically)
@sandwwraith is it really necessary to define a
SerialModule
for polymorphic classes? i have this class hierarchy:this is not working without registering a
SerialModule
(class B is not registered for polymorphic serialization in the scope of class A
), am i missing something? i seem to remember that in the previous release this step wasn’t necessary