发布版本的 Gson 解析问题 - 返回不正确的字符串
Gson parsing problem with release version - incorrect string is returned
您好,我的发行版 Gson 库有问题。
实际上,在我的应用程序的发布版本中,使用 new Gson().toJson(obj)
方法返回了不正确的字符串。
返回的字符串缺少我的对象的某些字段。发布版本是否可能需要一些缺失的选项?
这里有一些有用的信息:
obj
是 ArrayList<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
您需要 @Expose
而不是 @SerializedName
@Expose
public String a;
显然,解析后的 class 中的 toString()
方法是 Gson 库工作所必需的。
我不知道为什么,但如果你知道,请随时回复!
添加toString()
方法是给release版本添加信息的小技巧。您应该按照正确的方法进行操作并添加亲卫规则。
@Override
public String toString() {
return "MyClass{" +
"a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
在发布版本中 Android 编译器缩小并优化代码 [see Android doc]。 R8 删除了一些明显无用的信息,这些信息是 Gson 正确序列化对象所必需的。为了防止 R8 剥离这些信息,您需要将以下代码添加到 proguard-rules.pro 文件中:
-keep class com.giacomociardini.error02.entities.** { <fields>; }
其他细节你可以参考官方Gson GitHub repo上的这个例子。
我在 Model.java class 的内部 classes 中遇到了这个问题,所以我对那个项目的 proguard.pro 文件做了这个,内部 classes在proguard中用'$'定义所以,
-keep class path_to_models.Models$MyClass { <fields>; }
在AndroidStudio 3.4中,所有项目默认使用R8,所以如果你需要切换到proguard,那么:
android.enableR8 = gradle.properties 中的 false;要么
在你的 build.gradle.
中使用 Proguard = true
您好,我的发行版 Gson 库有问题。
实际上,在我的应用程序的发布版本中,使用 new Gson().toJson(obj)
方法返回了不正确的字符串。
返回的字符串缺少我的对象的某些字段。发布版本是否可能需要一些缺失的选项?
这里有一些有用的信息:
obj
是ArrayList<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
您需要 @Expose
而不是 @SerializedName
@Expose
public String a;
显然,解析后的 class 中的 toString()
方法是 Gson 库工作所必需的。
我不知道为什么,但如果你知道,请随时回复!
添加toString()
方法是给release版本添加信息的小技巧。您应该按照正确的方法进行操作并添加亲卫规则。
@Override
public String toString() {
return "MyClass{" +
"a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
在发布版本中 Android 编译器缩小并优化代码 [see Android doc]。 R8 删除了一些明显无用的信息,这些信息是 Gson 正确序列化对象所必需的。为了防止 R8 剥离这些信息,您需要将以下代码添加到 proguard-rules.pro 文件中:
-keep class com.giacomociardini.error02.entities.** { <fields>; }
其他细节你可以参考官方Gson GitHub repo上的这个例子。
我在 Model.java class 的内部 classes 中遇到了这个问题,所以我对那个项目的 proguard.pro 文件做了这个,内部 classes在proguard中用'$'定义所以,
-keep class path_to_models.Models$MyClass { <fields>; }
在AndroidStudio 3.4中,所有项目默认使用R8,所以如果你需要切换到proguard,那么:
android.enableR8 = gradle.properties 中的 false;要么 在你的 build.gradle.
中使用 Proguard = true