簡體   English   中英

HashMap Java中的序列化/反序列化 <Int,Object> 使用Gson

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM