Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
363 views
in Technique[技术] by (71.8m points)

java - Gson.toJson返回{},似乎ProGuard重命名了字段(Gson.toJson returns {} it seems ProGuard renames fields)

users Bug report shows Gson().toJson(obj) occasionally returns {} but for most users it works correct.

(用户的错误报告显示Gson().toJson(obj)偶尔返回{}但对于大多数用户而言,它可以正常工作。)

i have visited an user who faced the bug and debugged app on his phone and i made Toast to show what is sending to server and i saw Toast shows {} and also Records and ID aren't null .

(我拜访了一个遇到该错误并在手机上调试应用程序的用户,我让Toast展示了正在发送到服务器的内容,并且看到Toast展示了{} ,并且RecordsID都不为null 。)

here is what i have done.

(这是我所做的。)

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;
        }

}

And here i do serialize object

(我在这里序列化对象)

ClassA obj = new ClassA(ID,Records); 
String json = new Gson().toJson(obj);

but new Gson().toJson(obj ) for some users works correct but for some return {}

(但针对某些用户的new Gson().toJson(obj )可以正常工作,但对于某些返回{})

Server database shows some users sent data {} but some correct json .after some research i found new Gson().toJson(obj ) returns {} .no webservice problem and no database problem.

(服务器数据库显示一些用户发送了数据{}但是一些正确的json new Gson().toJson(obj研究,我发现new Gson().toJson(obj )返回了{} 。没有web服务问题,也没有数据库问题。)

Extra info

(额外信息)

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);

Database

(数据库)

id    | data
----------------
c89   | {"ID":"c89","Records":[{"T":0,"F":0,"D":"2019/04/11 05:48 PM"}]} correct one

c90   | {} bug

Null Input Test

(空输入测试)

i did below test and i found problem is beyond the null inputs

(我做了以下测试,发现问题超出了空输入)

ArrayList<ClassB> Records= new ArrayList<>();
ClassA obj = new ClassA(null,Records);    
Toast.makeText(getApplicationContext(),new Gson().toJson(obj ),Toast.LENGTH_LONG).show();

Toast shows {"Records":[]} .worse than upper condition never happens

(吐司显示{"Records":[]}糟糕的情况是永远不会发生)

And also IDE says

(还有IDE说)

if(ID!=null && Records!=null) <= this condition is always true 
ClassA obj = new ClassA(ID,Records); 

proguard-rules.pro

(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  ----------

How do i make it to work correct for all users?

(如何使所有用户都能正常使用?)

Comments

(评论)

This shouldn't be possible, you need more details on the {} case eg is it consistent, is it due to multi-threading, is it a specific JDK version

(这不可能,您需要了解{}情况的更多详细信息,例如是否一致,是否由于多线程而存在,是否是特定的JDK版本)

There isn't any multi-threading phenomena.for example, no Runnable no AsycTask no Thread .it's just a normal fragment which gets data from content provider and create json string.

(没有任何多线程现象。例如,没有Runnable没有AsycTask没有Thread这只是一个普通的片段,它从内容提供者那里获取数据并创建json字符串。)

Suggested solution has same result !

(建议的解决方案具有相同的结果!)

ClassA obj = new ClassA(ID,Records); 
Gson gson = new GsonBuilder().serializeNulls().create();
Toast.makeText(getActivity(), gson.toJson(obj), Toast.LENGTH_LONG).show();

Toast shows {} again.

(吐司再次显示{} 。)

  ask by Mr.AF translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is because ID and Records in ClassA are null.

(这是因为ClassA中的IDRecords为空。)

Gson does not serialize nulls by default and actually has a method to enable serializing nulls, which I almost always enable:

(Gson默认情况下不会序列化null,实际上有一种启用序列化null的方法,我几乎总是启用该方法:)

private static final Gson GSON = new GsonBuilder().serializeNulls().create();

I recommend keeping a static instance of a Gson around so you don't have to keep creating one each time you want to serialize.

(我建议保留一个Gson的静态实例,这样您就不必在每次要序列化时都继续创建一个实例。)

If you don't want to serialize nulls, then you have some other options to fix your code, such as having null checks in the constructor of ClassA .

(如果您不想序列化null,则可以使用其他一些方法来修复代码,例如在ClassA的构造函数中进行null检查。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...