Generic polymorphism example doesn't work with primitive and collection types
See original GitHub issueDescribe the bug
I’m trying to use example poly 16 with Response<List<String>>
. However the library doesn’t seem to be able to encode List
, String
, etc. in a polymorphic context.
To Reproduce
import kotlinx.serialization.*
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.*
@Serializable
abstract class Response<out T>
@Serializable
data class OkResponse<out T>(val data: T) : Response<T>()
fun main() {
val json = Json {
serializersModule = SerializersModule {
polymorphic(Response::class) {
subclass(OkResponse.serializer(PolymorphicSerializer(Any::class)))
}
}
}
val response1: Response<List<String>> = OkResponse(listOf("good"))
println(json.encodeToJsonElement(response1)) // Class 'SingletonList' is not registered for polymorphic serialization in the scope of 'Any'.
val response2: Response<String> = OkResponse("good")
println(json.encodeToJsonElement(response2)) // Class 'String' is not registered for polymorphic serialization in the scope of 'Any'.
}
However, using OkResponse
instead of Response
works (I guess because it’s not polymorphic):
val response: OkResponse<List<String>> = OkResponse(listOf("good"))
println(json.encodeToJsonElement(response)) // {"data":["good"]}
The error messages above aren’t helpful either. Using the guide and the error messages the next step would be straightforward:
polymorphic(Any::class) {
subclass(SingletonList::class) // not possible because class is private
subclass(String::class) // not possible: Serializer for String of kind STRING cannot be serialized polymorphically with class discriminator.
}
Expected behavior
In the serialization guide there’s no mention about these issues.
Primitives and collection types can be encoded in all other cases automatically by kotlinx-serialization
. I expect the same here too.
The initial example could either output the following or add a class discriminator like kotlin.String
.
{"type":"OkResponse","data":["good"]}
{"type":"OkResponse","data":"good"}
If that’s not possible, then:
- the guide should at least explain the limitation
- the guide should mention possible alternatives
- the related error messages should also be improved for standard types
Environment
- Kotlin version: 1.4.21
- Library version: 1.0.1
- Kotlin platforms: JVM
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:6
Top GitHub Comments
Another option for the “not possible: Serializer for String of kind STRING cannot be serialized polymorphically with class discriminator” is useArrayPolymorphism = true. But this results in ugly unpractical json IMHO. But it just works, it’s a pitty that there is no option to serialize primitives as json object with type attributes. That would make my solution above obsolete 😉. In Kotlin primitives are just objects, so why not just serialize them like that as well?
My reply is about the “not possible: Serializer for String of kind STRING cannot be serialized polymorphically with class discriminator” part of the problem. I’m not pretending to give an answer, I’m also just trying to figure things out. The following code below seems to fix your problem. Please comment if you see any issues with it 😉