首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Gson实现HashMap<Int、Object>的Java序列化/反序列化

使用Gson实现HashMap<Int、Object>的Java序列化/反序列化
EN

Stack Overflow用户
提问于 2015-11-20 01:38:08
回答 1查看 918关注 0票数 0

我正在尝试使用google的Gson库来序列化和反序列化Java语言中的HashMap。我想序列化这里显示的hashmap,将其保存到一个文件中,然后在以后从文件中读取并反序列化它。

HashMap如下

代码语言:javascript
复制
public static HashMap<Integer,HashMap <Integer, Type5Val>> type5Model = new HashMap<Integer, HashMap<Integer, Type5Val>>();

反序列化类的反序列化逻辑,以及到目前为止我基于web上找到的示例实现的object类。是:

代码语言:javascript
复制
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对象,创建一个字符串,然后尝试反序列化它。反序列化当前失败:

代码语言:javascript
复制
//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输出(这是有效的)。例外是在反序列化中。

代码语言:javascript
复制
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中给出更多关于反序列化的提示?

EN

回答 1

Stack Overflow用户

发布于 2016-02-07 11:35:31

在这一行上:

代码语言:javascript
复制
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,请执行以下操作:

代码语言:javascript
复制
new TypeToken<HashMap<Integer, HashMap<Integer, Type5Val>>>(){}.getType()

将结果传递给fromJson调用,而不是type5Model.getClass(),您应该会得到您所期望的结果。在一行中创建TypeToken,将其存储在temp变量中,然后传递该变量,而不是将所有内容都塞到一行中,可能会更具可读性。

另外,您在任何地方使用HashMap而不是Map的事实很容易出现错误。几乎可以肯定的是,您的大多数代码实际上只关心Map指定的行为,在这种情况下,应该只用Map编写。如果是这样的话,Gson选择使用哪种类型的Map将会很好地工作,并且这个错误永远不会发生。

但是,在没有TypeToken的情况下,您仍然会在其他地方得到另一个错误,因为Gson在不被告知某些对象应该属于Type5Val类的情况下是不会猜测的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33810694

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档