square/moshi

Can't serialize desugared models after updating to Kotlin 1.8.x

szymanskip opened this issue · 2 comments

We have updated our project from Kotlin 1.7.21 to 1.8.21.

After that, we started getting exception when trying to serialize a kotlin data class that holds a property of java.time.LocalDateTime - we've isolated this as the root cause.

This was tested with moshi versions 1.12.0 and 1.15.0 with the same result.

Other dependencies:

  • AGP: 7.3.1
  • compile/targetSdk: 34
  • minSdk: 24
  • desugar lib version: 1.2.3

Model class looks like this

data class Model(
    val id: String,
    val date: LocalDateTime? = null,
)

our custom adapter:

internal class LocalDateTimeAdapter {

    @FromJson
    fun fromJson(dateTime: String): LocalDateTime? =
        LocalDateTime.parse(
            dateTime,
            DateTimeFormatter.ISO_LOCAL_DATE_TIME
        )

    @ToJson
    fun toJson(dateTime: LocalDateTime): String =
        dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
}

and moshi instance:

val moshi: Moshi = Moshi.Builder()
        .add(KotlinJsonAdapterFactory())
        .add(LocalDateTimeAdapter())
        .build()

In the result, I am getting this exception

kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Could not compute caller for function: public constructor Model(id: kotlin.String, date: java.time.LocalDateTime? = ...) defined in com.example.myapplication.Model[DeserializedClassConstructorDescriptor@934d4e5] (member = null)
                at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:89)
                at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:62)
                at kotlin.SafePublicationLazyImpl.getValue(LazyJVM.kt:107)
                at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(KFunctionImpl.kt:62)
                at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:63)
                at kotlin.reflect.jvm.KCallablesJvm.setAccessible(KCallablesJvm.kt:82)
                at com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory.create(KotlinJsonAdapter.kt:230)
                at com.squareup.moshi.Moshi.adapter(Moshi.java:146)
                at com.squareup.moshi.Moshi.adapter(Moshi.java:106)
                at com.squareup.moshi.Moshi.adapter(Moshi.java:75)

From what I understand, Moshi/kotlin-reflect was not able to find a constructor with given signature because the actual signature uses j$.time.LocalDateTime and not java.time.LocalDateTime (or the other way around). When the project is built against kotlin 1.7.21, all works fine.

When we get rid of this property from model - it works
When we disable desugaring - it works

Is it a problem with kotlin-reflect/moshi/desugar or our specific setup?

Here is a sample project where it reproduces: https://github.com/szymanskip/moshi-kotlin-issue

This isn't a Moshi bug. I don't really have a solution for you, it would be better to ask for help on the android issue tracker for how to handle desugared java APIs in reflection.