I'm using Retrofit's `MoshiConverterFactory` for m...
# squarelibraries
l
I'm using Retrofit's
MoshiConverterFactory
for my API calls, however it doesn't support sealed classes containing `object`s. I'm trying to generate adapters for the sealed class hierarchy using
moshi-sealed
, but I still get the error
object Always cannot be serialized
. Here the hierarchy:
Copy code
@Keep
@JsonClass(generateAdapter = true, generator = "sealed:type")
sealed class TriggerCondition(val type: String) : Serializable {

    @Keep
    @TypeLabel("ALWAYS")
    object Always : TriggerCondition("ALWAYS")

    @Keep
    @TypeLabel("NIGHT")
    object Night : TriggerCondition("NIGHT")

    @Keep
    @TypeLabel("LIGHT_SENSOR")
    @JsonClass(generateAdapter = true)
    data class LightSensor(
        val sensorInfo: SensorInfo,
    ) : TriggerCondition("LIGHT_SENSOR")
}
z
This isn't enough info to help. How are you configuring your retrofit and Moshi instances? How are you defining your retrofit endpoint?
l
Copy code
fun create(client: OkHttpClient, baseUrl: String): AirConnectorApi =
            Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(client)
                .addConverterFactory(MoshiConverterFactory.create(moshiForKotlin))
                .addCallAdapterFactory(EitherCallAdapterFactory())
                .build()
                .create(AirConnectorApi::class.java)
Copy code
val moshiForKotlin = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()
This is the stack trace:
Copy code
java.lang.IllegalArgumentException: Unable to create converter for class myapp.gatewayapi.data.remote.air.model.AutomationList
                     for method AirConnectorApi.getAutomations
                 	at retrofit2.Utils.methodError(Utils.java:54)
                 	at retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:126)
                 	at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:85)
                 	at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:39)
                 	at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:202)
                 	at retrofit2.Retrofit$1.invoke(Retrofit.java:160)
                 	at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
                 	at $Proxy12.getAutomations(Unknown Source)
                 	at myapp.gatewayapi.data.remote.air.AirConnectorApi$DefaultImpls.getAutomations$default(AirConnectorApi.kt:142)
                 	at myapp.gatewayapi.data.remote.common.CommonConnectorApiAirImpl.getAutomations(CommonConnectorApiAirImpl.kt:267)
                 Caused by: java.lang.IllegalArgumentException: Cannot serialize object declaration myapp.gatewayapi.data.remote.air.model.TriggerCondition$Always
                 for class myapp.gatewayapi.data.remote.air.model.TriggerCondition triggerCondition
                 for class myapp.gatewayapi.data.remote.air.model.SensorTrigger
                 for interface myapp.gatewayapi.data.remote.air.model.AutomationTrigger trigger
                 for class myapp.gatewayapi.data.remote.air.model.ExistingAutomation
                 for java.util.List<myapp.gatewayapi.data.remote.air.model.ExistingAutomation> items
                 for class myapp.gatewayapi.data.remote.air.model.AutomationList
Containing class
ExistingAutomation
just implements
Serializable
, it's not annotated with
@JsonClass(...)
z
That stacktrace is complaining about something called AutomationList
l
Yes, that's the return type of the Retrofit API call
z
How is that class defined? It's not in your snippets above
l
Copy code
data class AutomationList(
    val total: Int,
    val items: List<ExistingAutomation>
)
z
And existingautomation?
l
Copy code
sealed interface Automation : Serializable {

    val name: String
    val trigger: AutomationTrigger
    val command: Command?
}

data class ExistingAutomation(
    val id: String,
    override val name: String,
    override val trigger: AutomationTrigger,
    override val command: Command?,
    @Json(name = "pending_state") val pendingState: DeviceState? = null,
    @Json(name = "provisioning_complete") val provisioningComplete: Boolean? = null,
    @Json(name = "provisioning_states") val provisioningStates: List<ProvisioningState>? = null,
) : Automation
But why is there:
Copy code
Caused by: java.lang.IllegalArgumentException: Cannot serialize object declaration myapp.gatewayapi.data.remote.air.model.TriggerCondition$Always
in my stacktrace?
z
I don't know
l
It points to `object
Always
So for me it looks as though the Retrofit
MoshiConverterFactory
was not able to cooperate with
moshi-sealed
annotated classes
z
I don't see anything obviously wrong there, but there may be other issues in your build. If you can make a reproducible sample that would help
l
Ok, thanks for the help!
z
Moshi converter factory works fine with Moshi-sealed
l
Do I have to register some special adapters with my Moshi instance to use moshi-sealed?
z
Only if you use reflection
But your snippet says you're using code gen
l
Yes
Ok, thank you very much for you time!
I will try to figure it out.