安卓开发中的ProGuard和Retrofit2 Gson转换器?

11
我在我的项目中使用了ProGuard,但在新的Gson().toJson(Request)中它提供了错误的数据。
我得到的输出结果为:
{"a":"manage","b":"689184d4418b6d975d9a8e53105d3382","c":"10","d":"76"}

取而代之

{"username":"manage","password":"689184d4418b6d975d9a8e53105d3382","value":"10","store":"76"}

我的ProGuard规则

-dontwarn okio.**
-dontwarn retrofit2.Platform$Java8
-dontwarn sun.misc.Unsafe
-dontwarn org.w3c.dom.bootstrap.DOMImplementationRegistry
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-keepclassmembers class rx.internal.util.unsafe.** {
    long producerIndex;
    long consumerIndex;
}

-keepclasseswithmembers class * {
    @retrofit2.http.* <methods>;
}
-keep class com.google.gson.** { *; }
-keep class com.google.inject.** { *; }

我正在使用

 compile 'com.squareup.retrofit2:converter-gson:2.0.0'

请问在 Android 中,retrofit2:converter-gson 的最新推荐 ProGuard 配置是什么?


最简单的方法是保留您想要与gson一起使用的类。否则,您可能需要查看gson是否有一个注释来为字段命名 - 这就是我在我的应用程序中使用jackson的方式。 - Dodge
如何保持类的一致性?有什么规则吗? - praj
5个回答

22

你可以选择保留使用Gson的类或者使用@SerializedName注解。

选项1(保留类):

// 保留包中所有类
-keep class com.example.app.json.** { *; }
// 或者保留特定的类
-keep class com.example.app.json.SpecificClass { *; }

选项2(使用@SerializedName注解):

public class YourJsonClass{
   @SerializedName("name") String username;
public MyClass(String username) { this.username = username; } }

第二个选项下,Proguard仍会混淆类和字段名,但是Gson可以使用注解来获取每个字段的正确名称。


在“-keep class com.example.app.json.SpecificClass”之后,我们是否仍然需要{ *; }? - user1090751

8

在您的JSON模型类中使用@Keep进行注释。


@ralphgabb通常会提供两个Proguard规则文件。一个来自SDK,另一个来自您的项目。SDK中的文件包含许多规则,其中包括保留使用Keep注释的类的规则。请确保您已经添加了该规则。 - Eugen Pechanec

5
请在您需要的类(如authToken)上使用android @Keep注释。
@Keep
data class AuthToken(
    var access_token: String,
    var token_type: String,
    var expires_in: String,
    var userName: String,
    var issued: String,
    var expires: String) {}

然后在 ProGuard 中添加以下行:
如果使用 androidx

-keep @androidx.annotation.Keep public class *

否则
 -keep @android.support.annotation.Keep public class *

0
如果您正在使用jsonschema2pojo,每个字段都会带有注释:

@SerializedName(field)

只需将此添加到您的proguard-rules.pro中,即可通过其@SerializedName保留每个字段名。
-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

0
在我的情况下,我正在使用Moshi和Retrofit处理JSON,但问题是一样的。它在调试中工作正常,但在使用ProGuard构建后,使用该模型的RecyclerView会因NullPointerException而崩溃,因为列表中充满了空模型对象,因为Moshi没有识别到任何字段。我认为Gson也会发生完全相同的事情。
一个解决方案是用其对应的序列化名称注释每个字段:
@Json(name="username") String username;

那样ProGuard就可以混淆变量名称而不会破坏转换。另一个解决方案是像Dodge建议的那样,在proguard-rules.pro文件中添加一个"keep"选项。
-keep public class com.example.model.User

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接