Kotlin / kotlinx.serialization

Kotlin multiplatform / multi-format serialization
Apache License 2.0
5.4k stars 620 forks source link

Polymorphic SerializersModule with generic class "Star projections in type arguments are not allowed" #944

Open elizarov opened 4 years ago

elizarov commented 4 years ago

Consider this code:

val responseModule = SerializersModule {
    polymorphic(Response::class) {
        subclass(OkResponse::class)
    }
}

@Serializable
abstract class Response<out T>

@Serializable
class OkResponse<out T>(val data: T) : Response<T>()

Running it produces:

Caused by: java.lang.IllegalArgumentException: Star projections in type arguments are not allowed, but had example.examplePoly17.OkResponse<*> (Kotlin reflection is not available)
benkuly commented 3 years ago

Is there a workaround for this issue? Using Any instead of * gives me Serializer for class 'Any' is not found

Burtan commented 3 years ago

Any new info on this?

kelposun commented 3 years ago

Same error

TxcA commented 3 years ago

GMT+8, 2021-03-21 01:50:06 , Use the latest version or the same error.

Whathecode commented 3 years ago

Not sure this is related, but I had the same error.

I found the following workaround: in my case, there was an interface constraint on the generic, and I could register the subclass as follows causing the error to disappear:

subclass(
    OkResponse::class,
    OkResponse.serializer( PolymorphicSerializer( InterfaceConstraint::class ) )
        as KSerializer<OkResponse<*>>
)
rocketraman commented 2 years ago

I can't serialize an open type hierarchy with a type parameter on the base class due to this issue, and I can't serialize a closed type hierarchy with a type parameter on the base class due to https://github.com/Kotlin/kotlinx.serialization/issues/1784. The only workaround I've found so far is to remove the generic entirely, which sucks.

leazardy commented 2 years ago

Any news folks?

sandwwraith commented 2 years ago

Nope

ForteScarlet commented 1 year ago

Any good solutions yet?

sandwwraith commented 1 year ago

@ForteScarlet You can specify serializer with a fixed T: subclass(OkResponse.serializer(SomeTSerializer))

SettingDust commented 10 months ago

You can specify serializer with a fixed T: subclass(OkResponse.serializer(SomeTSerializer))

Is there a way to make it work for polymorphicDefaultSerializer(Foo::class) { serializersModule.serializer() }? The serializer is registered as contextual.

pdvrieze commented 10 months ago

@SettingDust It can't really work without providing a concrete serializer. What happens is that the type parameter is actually resolved to a serializer, but, unsurprisingly, there is no serializer for *. Another consideration is that generic type parameters are erased at runtime, so there is no way to determine the "right" (de)serializer either. As such the only way is to either specify a member serializer or to have a serializer that itself can work out what to do with the member based upon the data/contents.