Сбой при анализе перечисления с помощью moshi и R8

#moshi

#moshi

Вопрос:

У меня есть следующие зависимости:

moshi-codegen: 1.10.0
kotlin: 1.4.10
Плагин для Android Gradle: 4.0.1
R8 включен в сборке.

Во время выполнения я получил следующую трассировку стека, когда Moshi пытается проанализировать перечисления

 java.lang.AssertionError: Missing field in e.f.a.k.c.b.a
        at com.squareup.moshi.StandardJsonAdapters$EnumJsonAdapter.<init>(SourceFile:246)
        at com.squareup.moshi.StandardJsonAdapters$1.create(SourceFile:67)
        at com.squareup.moshi.Moshi.adapter(SourceFile:141)
        at com.tsystems.tpay.data.client.models.ContactApiModelJsonAdapter.<init>(SourceFile:30)
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
        at com.squareup.moshi.internal.Util.generatedAdapter(SourceFile:553)
        at com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory.create(SourceFile:193)
        at com.squareup.moshi.Moshi.adapter(SourceFile:141)
        at com.squareup.moshi.Moshi.adapter(SourceFile:101)
        at com.squareup.moshi.Moshi.adapter(SourceFile:71)
        at com.squareup.moshi.CollectionJsonAdapter.newArrayListAdapter(SourceFile:52)
        at com.squareup.moshi.CollectionJsonAdapter$1.create(SourceFile:36)
        at com.squareup.moshi.Moshi.adapter(SourceFile:141)
        at com.squareup.moshi.Moshi.adapter(SourceFile:101)
        at p.z.a.a.a(SourceFile:91)
        at p.u.a(SourceFile:352)
        at p.u.b(SourceFile:335)
        at p.k.a(SourceFile:113)
        at p.k.a(SourceFile:82)
        at p.v.a(SourceFile:37)
        at p.u.a(SourceFile:192)
        at p.u$a.invoke(SourceFile:149)
        at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
        at $Proxy14.c(Unknown Source)
        at e.f.a.k.b.f$g.a(SourceFile:87)
        at i.b0.j.a.a.b(SourceFile:33)
        at j.a.v0.run(SourceFile:241)
        at j.a.g3.a.a(SourceFile:594)
        at j.a.g3.a.a(SourceFile:60)
        at j.a.g3.a$b.run(SourceFile:740)
     Caused by: java.lang.NoSuchFieldException: PERSONAL
        at java.lang.Class.getField(Class.java:1604)
        at com.squareup.moshi.StandardJsonAdapters$EnumJsonAdapter.<init>(SourceFile:240)
  

Согласно README, мне не нужно добавлять правила R8 вручную, но, возможно, перечисления являются исключениями?

Комментарии:

1. Можете ли вы проверить свой файл сопоставления — что proguard сделал с вашим классом enum?

2. В принципе, moshi терпит неудачу здесь github.com/square/moshi/blob/master/moshi/src/main/java/com /. … Это создает у меня впечатление, что перечисление не должно быть запутанным. Я пытаюсь найти конфигурацию moshi proguard. Можете ли вы проверить в библиотеке jar?

Ответ №1:

Да, перечисление должно обрабатываться немного по-другому, и в настоящее время существует ожидающий PR для обновления файла README (на момент написания) https://github.com/square/moshi/pull/1216 .

У вас есть 2 варианта:

  1. Добавьте @JsonClass(generateAdapter = false) поверх вашего определения перечисления.
  2. Добавьте правило proguard, чтобы сохранить поля вашего перечисления, например,
 -keepclassmembers enum your.model.package.YourEnum {
    <fields>;
    **[] values();
}
  

Причина:

Согласно приведенному здесь коду https://github.com/square/moshi/blob/0c85eae34af00ecbee46beaa5b25fb4af00fb9f2/moshi/src/main/resources/META-INF/proguard/moshi.pro#L10 , имена полей перечисления используются интегрированным EnumJsonAdapter . Также values() синтезируется компилятором Kotlin и используется EnumJsonAdapter косвенно.

Также обратите внимание, что в том же файле Moshi сгенерировал готовое правило proguard, которое наследуется вашим приложением:

 -keepclassmembers @com.squareup.moshi.JsonClass class * extends java.lang.Enum {
    <fields>;
    **[] values();
}
  

Это правило в основном применяется ко всем классам, аннотируемым @JsonClass аннотацией, поэтому, если вы добавите аннотацию (вариант № 1), ваш класс будет охвачен этим правилом.

В качестве альтернативы, если вы не хотите добавлять аннотацию, вы можете добавить правило специально для вашего класса, иначе вариант # 2.