[英]Serialization/Deserialization in Java of HashMap<Int,Object> using Gson
我正在尝试使用Google的Gson库对Java中的HashMap进行序列化和反序列化。 我想序列化此处显示的哈希图,将其保存到文件中,然后在以后从文件中读取并反序列化。
HashMap如下
public static HashMap<Integer,HashMap <Integer, Type5Val>> type5Model = new HashMap<Integer, HashMap<Integer, Type5Val>>();
到目前为止,我已经基于Web上的示例实现了反序列化的反序列化逻辑类和对象类。 是:
public class Type5Val implements Serializable,JsonDeserializer<Type5Val>{
public int modelLogLines;
public int modelTime;
@Override
public Type5Val deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
final JsonObject jsonObject = jsonElement.getAsJsonObject();
System.out.println("Print JSON Object" + jsonObject.getAsString());
final int t_modelLogLines = jsonObject.get("modelLogLines").getAsInt();
final int t_modelTime = jsonObject.get("modelTime").getAsInt();
//Populating
Type5Val val = new Type5Val();
val.modelLogLines = t_modelLogLines;
val.modelTime = t_modelTime;
return val;
}
}
以下是在测试函数中调用的用于序列化和反序列化的代码。 测试函数将上面的HashMap的Object序列化,创建一个字符串,然后尝试反序列化它。 反序列化当前失败:
//serialization code
public static String dump(){
// Configure Gson
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Type5Val.class, new Type5Val());
Gson g = gsonBuilder.create();
String json = g.toJson(type5Model);
return json;
}
//deserialization code
public static HashMap<Integer, HashMap<Integer,Type5Val>> undump(String json){
// Configure Gson
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Type5Val.class, new Type5Val());
Gson g = gsonBuilder.create();
HashMap<Integer,HashMap <Integer, Type5Val>> newModel = g.fromJson(json, type5Model.getClass());
return newModel;
}
public static void printMap(HashMap<Integer,HashMap<Integer,Type5Val>> modelInput){
Iterator<HashMap<Integer, Type5Val>> it = modelInput.values().iterator();
while(it.hasNext()){
HashMap<Integer,Type5Val> temp = it.next();
Iterator<Type5Val> it2 = temp.values().iterator();
while(it2.hasNext()){
Type5Val temp2 = it2.next();
System.out.println("Time: " + temp2.modelTime + " Lines: " + temp2.modelLogLines);
System.out.println(" Queue Size " + temp2.q.size() + "\n");
}
}
}
public static void testcase(){
System.out.println("Printing Initial Map");
printMap(type5Model);
//serialization
String s = dump();
System.out.println(s);
//deserialization
HashMap<Integer, HashMap<Integer,Type5Val>> newModel = undump(s);
System.out.println("Printing Map After Serialization/Deserialization");
printMap(newModel);
}
以下是我得到的例外,我在序列化后标记了JSON输出(有效)。 反序列化是一个例外。
Printing Initial Map
Time: 0 Lines: 39600000
Queue Size 0
Time: 0 Lines: 46800000
Queue Size 0
//Json output after serialization
{"1":{"1":{"modelLogLines":39600000,"modelTime":0,"q":[]},"2":{"modelLogLines":46800000,"modelTime":0,"q":[]}}}
Printing Map After Serialization/Deserialization
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.simontuffs.onejar.Boot.run(Boot.java:340)
at com.simontuffs.onejar.Boot.main(Boot.java:166)
Caused by: java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to java.util.HashMap
at violationChecker.type5Convert.printMap(type5Convert.java:207)
at violationChecker.type5Convert.testcase(type5Convert.java:259)
at violationChecker.type5Convert.main(type5Convert.java:294)
... 6 more
我在这里做错了什么? 谁能在Gson中反序列化中提供更多建议?
在这行上:
HashMap<Integer,HashMap <Integer, Type5Val>> newModel = g.fromJson(json, type5Model.getClass());
您要告诉Gson将String
反序列化为HashMap
。 只是一个HashMap
,而不是HashMap<Integer, HashMap<Integer, Type5Val>>
,因为有关泛型类型参数的所有信息都在运行时删除,传递给您的是运行时已知的type5Model
类型。 这迫使Gson猜测应该在HashMap
作为其键和值的类型,并且正在为值中的内部映射制作LinkedTreeMap
而不是HashMap
。
要为Gson提供完整的类型,包括通用类型参数,您将必须使用TypeToken
。 要创建适当的TypeToken
,请执行以下操作:
new TypeToken<HashMap<Integer, HashMap<Integer, Type5Val>>>(){}.getType()
将结果传递给type5Model.getClass()
的fromJson
调用,您应该得到期望的结果。 在TypeToken
上创建TypeToken
,将其存储在temp变量中,然后传递该变量,而不是将其全部TypeToken
一行,可能更具可读性。
另一个要注意的是,您在各处都使用HashMap
而不是Map
的事实易于出错。 几乎可以肯定,您的大多数代码仅真正关心Map
指定的行为,在这种情况下,应仅根据Map
编写。 如果是这样,Gson选择使用哪种类型的Map
将会很好,并且永远不会发生此错误。
但是,如果没有TypeToken
,在其他地方仍然会出现另一个错误,因为Gson永远不会猜测,而不会被告知某些对象应该属于Type5Val
类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.