启用 ProGuard 规则时 Gson 解析不起作用

Posted

技术标签:

【中文标题】启用 ProGuard 规则时 Gson 解析不起作用【英文标题】:Gson parsing is not working when ProGuard rule enabled 【发布时间】:2017-08-04 19:52:39 【问题描述】:

[![Proguard规则][gson解析2.8.0版]][android官方volley 1.0.0版]

启用 ProGuard 规则后,Gson 解析不起作用。我使用了 Volley 1.0.0 的正式版和 Gson 2.8.0 版。因此,每当我启用 ProGuard 规则时,Gson 解析都不起作用。我还在proguard-rules.pro 文件中添加了所需的规则,但它仍然无法正常工作。

依赖

compile 'com.google.code.gson:gson:2.8.0'
compile 'com.android.volley:volley:1.0.0'

ProGuard 规则:

-ignorewarnings
-keep class org.joda.**  *; 
-dontwarn org.joda.convert.FromString
-dontwarn org.joda.convert.ToString
-dontwarn org.joda.convert.**
-dontwarn org.joda.time.**
-keep class org.joda.time.**  *; 
-keep interface org.joda.time.**  *; 
-dontwarn org.mockito.**
-dontwarn sun.reflect.**
-dontwarn android.test.**
-dontwarn java.lang.management.**
-keepattributes Signature
-keep class com.google.gson.examples.android.model.**  *; 
-keep class com.google.gson.** *; 
-dontwarn com.fasterxml.jackson.**
-keep class com.fasterxml.jackson.**  *; 

解析方法

 private static void verifyResponse(final String response, final RequestCode requestCode, final IListener listener) throws IOException, ClassNotFoundException 

        if (listener != null) 
            ResponseStatus responseStatus;
            try 
                JSONObject jResult = new JSONObject(response);
                if (jResult.has("d")) 
                    String strResult = jResult.getString("d");
                    jResult = new JSONObject(strResult);
                    Debug.trace("ResponseStatusA " + jResult.toString());
                

                responseStatus = gson.fromJson(new JSONObject(jResult.toString()).toString(), ResponseStatus.class);


                Debug.trace("ResponseStatusB " + responseStatus.getStatus());
                processSuccess(jResult.toString(), responseStatus, requestCode, listener);
               /* if (responseStatus.isFail()) 
                    processError(responseStatus, listener);
                 else 

                    if (responseStatus.isSuccess()) 

                        listener.onHideProgressDialog();

                        processSuccess(jResult.toString(), responseStatus, requestCode, listener);
                    
                */
             catch (JsonSyntaxException | JSONException e) 
                e.printStackTrace();
            
        
    

【问题讨论】:

【参考方案1】:

您缺少ResponseStatus 的规则:

-keep class com.yourapp.yourpackage.ResponseStatus  *; 

可能发生的情况是 ProGuard 混淆了 ResponseStatus 的方法和字段,当 Gson 尝试设置它们时,它们的名称不再匹配。请记住,对于与 Gson 一起使用的每个模型类,您都需要一个 -keep class 规则。

【讨论】:

非常感谢@Mike Laren 实际上我已经在proguard rule -keep class com.example.mvc.codebase.models.***;中添加了我的模型包但是我的ResponseStatus类在另一个包中,所以我已经按照你所说的在 proguard 文件中添加了类,它的工作原理再次谢谢你【参考方案2】:

使用-keep 是一种不好的做法,你永远不应该这样做。你几乎从不想使用-keep;如果您确实需要 ProGuard 规则,您通常需要更具体的变体之一

-keepclassmembers - 这仅保护类的成员免于收缩和混淆。

-keepnames - 这允许缩小类和成员,但不允许混淆。也就是说,任何未使用的代码都将被删除。但保留的代码将保留其原始名称。

-keepclassmembernames - 未使用的类被删除,剩余的类被重命名,这些类中未使用的成员被删除,但剩余的成员保持原来的名称。

更多信息请阅读this

PS - 这就是我为 Gson 所做的

-keepclassmembernames class rscom.pojo.**  <fields>; 

【讨论】:

【参考方案3】:

在 Android Sutdio 的 proguard-rules.pro 文件中添加下面的 Proguard 规则。

Gson

-keep class sun.misc.Unsafe  *; 
-keep class com.google.gson.stream.**  *; 

让你的模型从 Proguard 中排除

-keepclassmembers class com.yourpackage.models**  <fields>; 
-keep class com.yourpackage.models *; 

【讨论】:

以上是关于启用 ProGuard 规则时 Gson 解析不起作用的主要内容,如果未能解决你的问题,请参考以下文章

当我在 GSON(使用枚举)上运行 Proguard 时应用程序崩溃

Android 上的 ProGuard 和 Gson (ClassCastException)

使用 GSON 库和 ProGuard 时 Android 崩溃

设置 minifyEnabled 为 true 时无法使用 GSON 解析 json 对象

应用proguard时Gson崩溃

启用 Pro Guard Jackson 解析器后不起作用