java - Gson.toJson 返回 null [ProGuard 问题]
问题描述
用户错误报告Gson().toJson(obj)
偶尔会显示返回{}
,但对于大多数用户来说它工作正常。
我拜访了一位用户,他在手机上遇到了错误并调试了应用程序,我Toast
展示了正在发送到服务器的内容,我看到了 Toast 节目{}
,而且记录和ID也没有null
。
这就是我所做的。
private class ClassA{
String ID;
ArrayList<ClassB> Records;
ClassA(String ID, ArrayList<ClassB> Records) {
this.ID= ID;
this.Records= Records;
}
}
private class ClassB {
int T;
int F;
String D;
ClassB (int T, int F, String D) {
this.T= T;
this.F = F;
this.D= D;
}
}
在这里我序列化对象
ClassA obj = new ClassA(ID,Records);
String json = new Gson().toJson(obj);
但是new Gson().toJson(obj
)对于某些用户来说是正确的,但对于一些回报{}
服务器数据库显示一些用户发送的数据{}
,但一些正确的 json。经过一些研究,我发现new Gson().toJson(obj
)返回{}
。没有 web 服务问题,也没有数据库问题。
额外信息
ArrayList<ClassB> Records= new ArrayList<>();
Records.add(new ClassB(Integer.valueOf(t.toString()), Integer.valueOf(f.toString()),d.toString()));
ClassA obj = new ClassA(ID,Records);
String json = new Gson().toJson(obj);
数据库
id | data
----------------
c89 | {"ID":"c89","Records":[{"T":0,"F":0,"D":"2019/04/11 05:48 PM"}]} correct one
c90 | {} bug
空输入测试
我做了下面的测试,我发现问题超出了空输入
ArrayList<ClassB> Records= new ArrayList<>();
ClassA obj = new ClassA(null,Records);
Toast.makeText(getApplicationContext(),new Gson().toJson(obj ),Toast.LENGTH_LONG).show();
Toast 显示{"Records":[]}
.worse 比上限条件永远不会发生
IDE还说
if(ID!=null && Records!=null) <= this condition is always true
ClassA obj = new ClassA(ID,Records);
proguard-rules.pro
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { <fields>; }
# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}
##---------------End: proguard configuration for Gson ----------
我如何使它对所有用户都正确工作?
注释
这是不可能的,您需要有关 {} 案例的更多详细信息,例如它是否一致、是否由于多线程、是否是特定的 JDK 版本
没有任何多线程现象。例如,不不不Runnable
。它只是一个正常的片段,它从内容提供者获取数据并创建 json 字符串。AsycTask
Thread
建议的解决方案具有相同的结果!
ClassA obj = new ClassA(ID,Records);
Gson gson = new GsonBuilder().serializeNulls().create();
Toast.makeText(getActivity(), gson.toJson(obj), Toast.LENGTH_LONG).show();
吐司{}
再次出现。
解决方案
只是我的猜测,我看到您在其中一个评论中提到ClassA
并且ClassB
是片段中的内部类。所以,也许你可以尝试一些事情,如果还没有的话。
第一:把它们改成静态内部类怎么样?
private static class ClassA {
...
}
private static class ClassB {
...
}
将类声明为内部类,因为没有其他人使用它是可以的,我有时也这样做。但是非静态内部类依赖于其父对象实例,因此当它只是一个简单的 bean/DTO 类时,将它们声明为静态内部类要安全得多。
第二: 尝试摆弄有关这些类的Proguard配置
这是关于设置Proguard以保留内部类的 stackoverflow 问题。
查看
-keep class <your packge name>.** { <fields>; }
零件
第三: 也许尝试将这些类提取到普通类中,以缩小可疑区域。
如果它仍然不起作用,那么问题可能出在其他地方,可能是客户端移动设备的某个特定构建/版本或其他东西。
推荐阅读
- ruby-on-rails - 安全公告:GHSA-cfjv-5498-mph5 actionview (RubyGems)
- gitlab - Gitlab 无法删除 ssh 密钥。不在 UI 中,但仍然有效
- reactjs - 如果我不想再在下拉列表中过滤,如何返回默认产品列表
- laravel - 无法在 Laravel Homestead 上安装 Socialite:内存限制错误
- automated-tests - Cy.click 失败,因为目标元素被禁用或其部分可见
- django - 无法通过 group_send 向 Django 频道发送消息
- scala - http4s 中的自定义普罗米修斯指标
- java - org.mongodb.driver.connection : 连接池后台维护任务 com.mongodb.MongoSocketOpenException 抛出异常
- c# - C# WriteAllText 仅以编码 UTF8 格式写入
- java - Tomcat 服务器无法启动