【问题标题】:Gson parsing problem with release version - incorrect string is returned发布版本的 Gson 解析问题 - 返回不正确的字符串
【发布时间】:2019-11-21 12:09:22
【问题描述】:

您好,我在发布版本中遇到了库 Gson 的问题。

实际上,在我的应用程序的发布版本中,使用new Gson().toJson(obj) 方法会返回一个不正确的字符串。

返回的字符串缺少我的对象的某些字段。发布版本是否可能需要一些缺少的选项?

以下是一些有用的信息:

  • objArrayList<MyClass> 的一个实例
  • 我正在使用implementation 'com.google.code.gson:gson:2.8.5'
  • 我正在使用Android Studio 3.5.1

MyClass 是这样构建的:

public class MyClass{

    @SerializedName("a")
    private String a;

    @SerializedName("b")
    private Integer b;

    @SerializedName("c")
    private String c;

    @SerializedName("d")
    private String d;

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    ...

}

示例:

MyClass example = new MyClass("a","b","c","d");

ArrayList<MyClass> listExample = new ArrayList<MyClass>();
listExample.add(example);

String strObj = new Gson().toJson(listExample);

当前输出:

[ 
   { 
      "b":"b",
      "c":"c",
      "d":"d",
   }
]

预期输出

[ 
   { 
      "a":"a",
      "b":"b",
      "c":"c",
      "d":"d",
   }
]

要重现错误,只需关注 github: https://github.com/Ciardini/error02

【问题讨论】:

  • 你能展示整个MyClass 的所有方法和构造函数吗?
  • @MichałZiober 没什么,MyClass 有两个构造函数,一个为空,另一个包含所有字段。与示例一样,该类具有所有 get 和 set 方法,我更喜欢不共享该类,因为它有 50 多个字段。今天我将尝试重新创建一个有错误的小样本并将其发布到 github 上。

标签: java android json gson release


【解决方案1】:

在发布版本中,Android 编译器缩小和优化代码[see Android doc]。 R8 删除了一些明显无用的信息,这些信息是 Gson 正确序列化对象所必需的。为防止 R8 剥离此信息,您需要在 proguard-rules.pro 文件中添加以下代码:

-keep class com.giacomociardini.error02.entities.** { &lt;fields&gt;; }

其他细节可以参考Gson官方GitHub repo上的这个例子。

【讨论】:

  • 确实有效!非常感谢,我认为 android 会减小文件尺寸,但我不知道存在定义什么是什么不是什么的规则。
【解决方案2】:

显然需要解析类中的toString()方法才能使Gson库正常工作。

我不知道为什么,但如果您知道,请随时回复!

添加toString() 方法是在发布版本中添加信息的一个小技巧。您应该按照正确的方法进行操作并添加保护规则。

@Override
public String toString() {
    return "MyClass{" +
            "a='" + a + '\'' +
            ", b='" + b + '\'' +
            ", c='" + c + '\'' +
            ", d='" + d + '\'' +
            '}';
}

【讨论】:

    【解决方案3】:

    您需要@Expose 支持@SerializedName

    @Expose
    public String a;
    

    【讨论】:

    • 这样的@SerializedName("a") @Expose private Integer a;@Expose private Integer a; 不起作用。
    【解决方案4】:

    我在 Model.java 类的内部类中遇到了这个问题,所以我对该项目的 proguard.pro 文件执行了此操作,内部类在 proguard 中使用“$”定义,所以,

    -keep class path_to_models.Models$MyClass { <fields>; }
    

    在 Android Studio 3.4 中,所有项目默认使用 R8,所以如果您需要切换到 proguard,那么:

    android.enableR8 = gradle.properties 中的 false;要么 在 build.gradle 中使用 useProguard = true。

    【讨论】:

      猜你喜欢
      • 2015-12-19
      • 2014-11-13
      • 2013-10-11
      • 2019-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多