使用 gson 库将自定义对象的 ArrayList 转换为 JSON,检索这些自定义对象时出现 ClassCastException

Converted ArrayList of custom objects to JSON using gson library, ClassCastException when retrieving back those custom objects

我已经使用 Google 的 GSON 库将自定义对象的 ArrayList 转换为 JSON,以便将其存储到 SharedPreferences。 ArrayList中存储的对象class是这样的:

class CustomObject {
  String name;
  Map<String, Long>  topGrades;
  Map<String, Long> lowestGrades;

  CustomObject(String name, Map<String, Long>  topGrades, Map<String, Long>  lowestGrades) {
    this.name = name;
    this.lowestGrades = lowestGrades;
    this.topGrades = topGrades;
  }
}

我将 CustomObjectArrayList 个对象保存到 SharedPreferences,例如:

List<CustomObject> dataList = new ArrayList<>();
//Populate the list with objects of type CustomObject
...
SharedPreferences sharedPreferences = getActivity().getSharedPreferences(
                    "tests.dataSharedPreferences", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String dataListJson = gson.toJson(dataList);
editor.putString("tests.dataListJsonKey", dataListJson);
editor.commit();

我从 JSON 中检索了 List,例如:

SharedPreferences sharedPreferences = getActivity().getSharedPreferences("tests.dataSharedPreferences", Context.MODE_PRIVATE);
            String dataJson = sharedPreferences.getString("tests.dataListJsonKey", "");

            Gson gson = new Gson();
            final List<CustomObject> dataList = gson.fromJson(dataJson, ArrayList.class);

到目前为止还不错。但是现在为了将上面 dataList 中所有 CustomObjectname 放入一个字符串数组中,在下面的循环中,我试图从dataList, 但是我得到了ClassCastException:

        String[] namesArray = new String[dataList.size()];

        for (int x=0; x<namesArray.length; x++) {
            CustomObject customObject = dataList.get(x);//********ClassCastException********************************
            namesArray[x] = customObject.name;
        }

我得到了

06-18 12:28:11.689: E/AndroidRuntime(1536): Caused by: java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to tests.CustomObject

问题是为什么以及解决方案是什么?

Gson 必须知道要转换成的对象类型。也就是说,为了序列化它必须知道确切的类型。当您将类型作为 ArrayList.class 传递时,它不会向 Gson 提供有关您的对象的完整必要信息。

您可以做的一件事是创建一个包含您的 ArrayList 的包装器 class。然后将 class 作为第二个参数提供给 Gson。

class Wrapper {

    ArrayList<CustomObject> dataList; 
    //constrctor 
    public Wrapper() {
       //empty constructor for Gson
    }
    //setter for dataList
    public void setDataList(ArrayList<CustomObject> dataList){
        this.dataList = dataList;
    }

}

试试这个序列化和反序列化:

Wrapper wrapper = new Wrapper();
//populate list
wrapper.setDataList(list);

//serialize
String dataListJson = gson.toJson(wrapper);

//deserialize
Gson gson = new Gson();
Wrapper dataWrapper = gson.fromJson(dataListJson, Wrapper.class);

只需替换

 final List<CustomObject> dataList = gson.fromJson(dataJson, ArrayList.class);

final List<CustomObject> dataList = gson.fromJson(data, new TypeToken<List<CustomObject>>() {
          }.getType());