Android - JSON 存储列表包含在应用退出、重新打开时恢复为超类的对象
Posted
技术标签:
【中文标题】Android - JSON 存储列表包含在应用退出、重新打开时恢复为超类的对象【英文标题】:Android - JSON stored list contains objects that revert to superclass when app is exited, reopened 【发布时间】:2013-03-31 19:46:52 【问题描述】:我有一个ArrayList <GeneralTemplate> items
在整个程序中,我添加了作为 GeneralTemplate 子类的例程,即 items.add(new Routine("Test"));
,一切都很好。
最重要的是,我可以做到以下几点.. Routine myRoutine = items.get(position);
我正在使用 Google 的 GSON 库将这个大项目列表保存在 JSON 格式的特殊数据对象中。我相信这可能是问题所在。
此数据对象包含ArrayList <GeneralTemplate> items
。在我的程序中,我可以看到存储在项目列表中的例程确实是Routine
对象。然后我使用下面的代码保存它。我已经使用调试器遵循了这个过程,并且当我设置RoutineList 时,Routine 对象的维护没有问题。
// Global save String method
public static void save()
Editor editor = sharedPreferences.edit();
RoutineData tempSaveObject = new RoutineData();
tempSaveObject.setRoutineList(routineList);
String routineListInJSON = gson.toJson(tempSaveObject);
editor.putString(ROUTINE_LIST, routineListInJSON).commit();
当我重新启动应用程序并检索数据时会出现问题。列表中的所有项目都恢复为GeneralTemplate
对象,并且不能通过Routine routine = (Routine) items.get(position)
转换回Routine
-> ClassCastException
(下面的加载代码)
// Get a global sharedPreferences object that can be used amongst Activities
sharedPreferences = this.getSharedPreferences(SHARED_PREFS, Context.MODE_PRIVATE);
if (sharedPreferences.contains(ROUTINE_LIST))
String routineListJSON = sharedPreferences.getString(ROUTINE_LIST, null);
routineDataObject = gson.fromJson(routineListJSON, RoutineData.class);
routineList = routineDataObject.getRoutineList();
else
routineList = new ArrayList<GeneralTemplate>();
因此,我无法访问特定的方法和变量,因为我无法重新获得子类上下文。这个问题还有其他几个例子,所以如果有任何好的解决方案,你的好人都知道,那将有很大帮助。
谢谢!
排序:
Genson JSON 库。
https://code.google.com/p/genson/downloads/detail?name=genson-0.94.jar&can=2&q=
让事情变得如此简单,无需自定义序列化器/反序列化器。默认情况下处理所有深度多态性的东西。
如 Eugen 的回答所示实施
【问题讨论】:
请说明你是如何重新加载的。 啊,是的,很关键! 【参考方案1】:这是因为您有一个 GeneralTemplate 列表,虽然序列化 Gson 知道列表中每个元素的具体类型,但在反序列化期间 Gson 不知道要反序列化的类型(因为它是一般模板)。
我不确定,但看起来他们有一些 contrib(不是 Gson 的一部分)允许在序列化流中添加类型信息,这允许 Gson 反序列化回正确的类型。
您也可以尝试Genson 库,开箱即用支持处理多态类型。它也具有 Gson 和其他一些提供的功能。以下是实现它的方法:
// first configure your Genson instance to enable polymorphic types support and
// serialization based on concrete types
Genson genson = new Genson.Builder()
.setWithClassMetadata(true)
.setUseRuntimeTypeForSerialization(true)
.create();
// and now just use it to serialize/deser
String json = genson.serialize(routineData);
RoutineData data = genson.deserialize(json, RoutineData.class);
编辑 问题解决了。例程类没有默认构造函数。将 @JsonProperty("name") 放在 ctr 参数上并使用 gensons 之前的配置解决了问题。
【讨论】:
这是一个很好的答案,但是如果您不想使用其他库,您也可以向 GeneralTemplate 添加一个私有成员,其中包含作为字符串的类名。这显然会毫无问题地进行序列化和反序列化。然后,您可以在反序列化 JSON 时使用 ClassForName() 来创建正确类型的新实例。您遇到的问题是,正如 eugen 所说,您的反序列化类型始终是基类。 在您描述的解决方案中,他必须为他需要处理的所有多态类型实现自定义反序列化器。对于应该由 lib 处理的事情来说,这听起来有点太多了:/ 嗯,Genson 看起来很方便。有没有像 GSON 这样的 .jar 文件下载它?直到最近才启动并运行 Git,还不是很熟悉 @mgibson 太好了,你喜欢 :) 是的,如果你使用 maven,请使用这里的依赖项 code.google.com/p/genson/wiki/GettingStarted#Download,如果你只是想 dl jar,你可以在这里找到它 mvnrepository.com/artifact/com.owlike/genson/0.94(你有那里有下载链接) @mgibson 顺便说一下,你不应该获取库的源代码并自行打包,因为主干中的代码与发布的版本不匹配以上是关于Android - JSON 存储列表包含在应用退出、重新打开时恢复为超类的对象的主要内容,如果未能解决你的问题,请参考以下文章
Android 应用程序在设备上显示列表,但从 Playstore 下载时
在 android Studio 中迭代包含列表/数组的 JSON 对象
如何将大型 JSON 数据从服务器存储到 SQLITE Android?
如何将本地存储中的 JSON 对象添加到 Android Studio 上的片段列表
python - 如何在python中附加一个列表时处理异常,其中包含从存储从.json文件读取的数据的dict读取的数据?