kotlinx.serialization icon indicating copy to clipboard operation
kotlinx.serialization copied to clipboard

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

Open elizarov opened this issue 5 years ago • 12 comments

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)

elizarov avatar Jul 28 '20 15:07 elizarov

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

benkuly avatar Jan 20 '21 09:01 benkuly

Any new info on this?

Burtan avatar Feb 18 '21 06:02 Burtan

Same error

kelposun avatar Mar 17 '21 12:03 kelposun

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

TxcA avatar Mar 20 '21 17:03 TxcA

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<*>>
)

Whathecode avatar May 05 '21 13:05 Whathecode

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.

rocketraman avatar Jan 19 '22 16:01 rocketraman

Any news folks?

leazardy avatar Jul 16 '22 15:07 leazardy

Nope

sandwwraith avatar Jul 19 '22 13:07 sandwwraith

Any good solutions yet?

ForteScarlet avatar Nov 10 '22 17:11 ForteScarlet

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

sandwwraith avatar Nov 11 '22 14:11 sandwwraith

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.

SettingDust avatar Dec 26 '23 12:12 SettingDust

@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.

pdvrieze avatar Dec 27 '23 10:12 pdvrieze