我有一个类型为 A 的自定义对象和一个包含类型为 B 的自定义对象的 ArrayList,我想使用 gson 将其存储在我的共享首选项中。对象 A 工作没有问题,但是当我尝试存储对象 B 的列表或什至只是 B 的一个实例时,出现以下错误消息:
2019-01-07 13:05:21.610 28295-28295/com.example.aev.quizzle E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.aev.quizzle, PID: 28295
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.aev.quizzle/com.example.aev.quizzle.activities.MapsActivity}: java.lang.IllegalArgumentException: class android.content.res.ColorStateList declares multiple JSON fields named mChangingConfigurations
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3194)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3302)
at android.app.ActivityThread.-wrap12(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
Caused by: java.lang.IllegalArgumentException: class android.content.res.ColorStateList declares multiple JSON fields named mChangingConfigurations
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:172)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
at com.google.gson.Gson.getAdapter(Gson.java:458)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:117)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:166)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
at com.google.gson.Gson.getAdapter(Gson.java:458)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:117)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:166)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
at com.google.gson.Gson.getAdapter(Gson.java:458)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:56)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
at com.google.gson.Gson.toJson(Gson.java:704)
at com.google.gson.Gson.toJson(Gson.java:683)
at com.google.gson.Gson.toJson(Gson.java:638)
at com.google.gson.Gson.toJson(Gson.java:618)
at com.example.aev.quizzle.activities.MapsActivity.generateThemes(MapsActivity.java:592)
at com.example.aev.quizzle.activities.MapsActivity.onCreate(MapsActivity.java:164)
at android.app.Activity.performCreate(Activity.java:7383)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3147)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3302)
at android.app.ActivityThread.-wrap12(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
我这样存储数组列表:
themes = new ArrayList<>();
themes.add(new Theme(0, this));
themes.add(new Theme(1, this));
themes.add(new Theme(2, this));
String jsonTheme = gson.toJson(themes);
prefsEditor.putString("themes", jsonTheme);
prefsEditor.commit();
我的类(class)主题是这样的:
public class Theme implements Parcelable {
public ImageView icon;
public int themeID;
//public Question[] questions = new Question[14];
public List<Question> questions = new ArrayList<>();
boolean unlocked;
Context context;
我已经看到类似的问题,即父类(super class)和对象中的相同变量名应该存储的问题,但在我的例子中,我没有在我的主题类中扩展另一个类。 错误指向行说
String jsonTheme = gson.toJson(themes);
我是不是错误地处理了 gson 对象,还是遗漏了什么?
最佳答案
使用@Transient
是解决这个序列化问题的一种方法。您可能还注意到,在反序列化后,您需要将这些 ImageView
和 Context
设置为每个反序列化的 Theme
,这可能是一个小问题。
您还可以考虑将要持久保存的数据与 View 和上下文等 transient 数据分开。只看过你代码的一小部分,你的结构可能是这样的:
类似于:
public class Theme {
public ImageView icon;
Context context;
ThemeData themeData
public Theme(Context contect, ImageView icon, ThemeData themeData) {
this.context = context;
this.icon = icon;
themeData = themeData;
}
public void doSomethingWithThemeDataAndViewAndContext() {
// whatever you need to do in Theme
}
}
其中 ThemeData
然后包含所有非 transient 字段,然后您将持久保存到 SharedPreferences
:
public class ThemeData {
public int themeID;
//public Question[] questions = new Question[14];
public List<Question> questions = new ArrayList<>();
boolean unlocked;
}
另请注意:我认为,如果您使用 GSON 序列化主题并将其保存为 SharedPreferences
中的 JSON 字符串,则不需要实现 Parcelable
,所以我删除它。
关于java - gson.toJson 声明了多个名为 XX 的 JSON 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54074356/