3

我有一个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 = (Routine) items.get(position)->转换回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>();     
    }

因此,我无法访问特定的方法和变量,因为我无法重新获得子类上下文。这个问题还有其他几个例子,所以如果有任何好的解决方案,你的好人都知道,这将有很大帮助。

谢谢!

排序:

根森 JSON 库。

https://code.google.com/p/genson/downloads/detail?name=genson-0.94.jar&can=2&q=

让事情变得如此简单,无需自定义序列化器/反序列化器。默认情况下处理所有深度多态性的东西。

如Eugen的答案所示实施

4

1 回答 1

0

这是因为您有一个 GeneralTemplate 列表,而序列化 Gson 知道列表中每个元素的具体类型,但在反序列化期间,Gson 不知道要反序列化的类型(因为它是 GeneralTemplate 的列表)。

我不确定,但看起来他们有一些 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 以前的配置解决了这个问题。

于 2013-03-31T21:00:34.713 回答