使用 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;
}
}
我将 CustomObject
的 ArrayList
个对象保存到 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
中所有 CustomObject
的 name
放入一个字符串数组中,在下面的循环中,我试图从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());
我已经使用 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;
}
}
我将 CustomObject
的 ArrayList
个对象保存到 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
中所有 CustomObject
的 name
放入一个字符串数组中,在下面的循环中,我试图从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());