Moshi: Fields parsed as default (null, 0, etc) in AGBP 3.4.0 when Proguarded

Created on 13 May 2019  路  6Comments  路  Source: square/moshi

MainActivity.kt:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Moshi.Builder().build().adapter(Foo::class.java)
            .fromJson("""{"bar": "Hello World!"}""")
            .also {
                Log.d("TAG", "${it}")
            }
    }
}

data class Foo(val bar: String)

AGBP 3.3.1 outputs
Proguard-enabled: Foo(bar=Hello World!)
Proguard-disabled: Foo(bar=Hello World!)

AGBP 3.4.0 outputs
Proguard-enabled: Foo(bar=null)
Proguard-disabled: Foo(bar=Hello World!)

I'm not 100% sure that this issue is unique to Moshi. Use the codegen feature to work around this issue.

ProGuard

Most helpful comment

I added the following rule and it worked.

-keepclassmembers, allowobfuscation class * {
   @com.squareup.moshi.Json <fields>;
}

(From: https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg#L22)

All 6 comments

I have a similar issue when I set

minifyEnabled true

After some tries/fails I figure out it happened because of some issue related to R8 and Moshi. R8 is enabled by default when we are using AGP 3.4.0 and above. The issue also happens with 3.5.0-beta01.

My sample is pretty similar to @nukeforum

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Moshi.Builder().build().adapter(Foo::class.java)
            .fromJson("{\"bar\": { \"message\":\"Hello World!\"}}")
            .also {
                Log.d("TAG", "${it}")
            }
    }

    data class Foo(@field:Json(name = "bar") val bar: Bar)
    data class Bar(@field:Json(name = "message") val message: String)
}
  • build.gradle:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.gmail.esdrasdl.moshitest"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        debug {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.core:core-ktx:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation("com.squareup.moshi:moshi:1.7.0")
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}

I used the folowing versions to test it:
com.squareup.moshi:moshi:1.8.0
com.squareup.moshi:moshi:1.7.0

  • gradle.properties
org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
android.enableJetifier=true
kotlin.code.style=official
  • R8

Current version is: 1.4.77 (build b74371231cb896b02f83285efb055b7c00ff64d8 from go/r8bot (luci-r8-ci-archive-0-eqqf)).

My proguard-rules.pro file is the same described here

The expected result: Foo(bar=Bar(message=Hello World!))
The result: Foo(bar=null)

The only workaround I figured out was to turn off R8 (and use ProGuard instead) and remove some rules not compatible with ProGuard.
In my gradle.properties file I added the following line:
android.enableR8=false

It bothers me because it affects how we retrieve information by our API. It happens with retrofit and converter-moshi.

Did I miss something?

BTW, there is an open issue on Google Issue Tracker about it:
https://issuetracker.google.com/issues/131127414

I added the following rule and it worked.

-keepclassmembers, allowobfuscation class * {
   @com.squareup.moshi.Json <fields>;
}

(From: https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg#L22)

I think @esdrasdl's workaround is a good choice for now, will keep an eye on the linked issue tracker issue for improvements to matching

this still happening with me even after @esdrasdl solution! it happens with only one data class any, explanation ?

this still happening with me even after @esdrasdl solution! it happens with only one data class any, explanation ?

I'm using another module and i found that i need to add my data class in app proguard

Was this page helpful?
0 / 5 - 0 ratings