square/moshi

Bug with ProGuard and R8

ArcherEmiya05 opened this issue · 3 comments

Encountering a weird bug with debug variant that has minify and shrink enable. The serialization from JSON string to Kotlin data class works when ProGuard and R8 is enable.

Gradle

buildTypes {
        debug {
            isMinifyEnabled = true // MOSHI FAIL IF REMOVED
            isShrinkResources = true // MOSHI FAIL IF REMOVED
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            ) // MOSHI FAIL IF REMOVED

            configure<CrashlyticsExtension> {
                // No need during development, enabling it also prevents Gradle to work offline
                mappingFileUploadEnabled = false
            }

            signingConfig = signingConfigs.getByName("debug")
        }
        release {
            isMinifyEnabled = true
            isShrinkResources = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )

            signingConfig = signingConfigs.getByName("release")
        }
    }

ProGuard Rules:

# Moshi
-keepclasseswithmembers class * {
    @com.squareup.moshi.* <methods>;
}

Kotlin data class

object AppConfig {

    @Keep
    data class Remote(
        val someConfigParam: String = ""
    ) {
        /**
         * Required properties or fields of this data class, can be use for quick checking using any() with specified predicate
         * @see Iterable.any(predicate: (T) -> Boolean)
         * */
        val requiredProperties
            get() = listOf(
                someConfigParam
            )
    }

}

Object

object AppConfig {

    @Keep
    data class Remote(
        val sampleProp: String = DEFAULT_VALUE_STRING
    )

}

Caller

// Convert JSON String to this data class
parser.fromJsonString<AppConfig.Remote>(jsonString, AppConfig.Remote::class.java)

Parser implementation

    override fun <T> fromJsonString(jsonString: String?, type: Type): T? {

        if (jsonString.isNullOrBlank()) {
            return null
        }

        return try {
            moshi.adapter<T>(type).fromJson(jsonString)
        }
        catch (e: Exception) {
            e.printStackTrace()
            null
        }

    }

Exception

java.lang.IllegalArgumentException: Cannot serialize Kotlin type com.sample.app.utils.AppConfig$Remote. Reflective serialization of Kotlin classes without using kotlin-reflect has undefined and unexpected behavior. Please use KotlinJsonAdapterFactory from the moshi-kotlin artifact or use code gen from the moshi-kotlin-codegen artifact.

AGP: 8.2.2
Gradle: 8.2
Moshi and Moshi Codegen: 1.15.0

It works if @JsonClass(generateAdapter = true) was added below @Keep annotation. What I don't get is if I enable the R8 and ProGuard in debug variant then it works even without @JsonClass annotation.

Same issue here. Any news?

This isn't really a Moshi bug. Sounds like you're trying to learn how to use proguard rules in debug builds, which is best asked on other forums like Stackoverflow.