2015-10-23 26 views
0

我有這樣爲什麼左側忽視的類型 - 傑克遜deserialisation

class POJO { 
    Map<Integer, Integer> map; 
    //Getter and Setter for map here 
} 

一個POJO和我有一個JSON(POJO列表)

[ 
    { 
     "200": 10 
    }, 
    { 
     "20": 100, 
     "30": 400 
    } 
] 

在傑克遜反序列化,如果我做

String s = ... //s has the above json 
List<POJO> pojoList = mapper.readValue(s, new TypeReference<List<POJO>>() {}); 
System.out.println(pojoList.get(0).getMap().get(20)); //prints 100 

那麼就沒有問題

但是,如果使用泛型列表像

List<POJO> pojoList = mapper.readValue(s, List.class); 

然後在System.out.println它拋出ClassCastException

java.util.LinkedHashMap cannot be cast to mycode.model.POJO 

我明白,如果我只是告訴傑克遜List它反序列化的每個對象爲地圖,而不是作爲類型POJO。所以,當我嘗試訪問pojoList.get(0).getMap()它拋出異常

(注:打印pojoList.get(0)沒有給出問題並打印{"200":10}

我的問題是,爲什麼沒有把它反序列化本身期間拋出異常。 LHS上的對象類型是否被忽略?

謝謝..

回答

2

我的問題是,爲什麼沒有把它反序列化 本身期間拋出異常。 LHS上的對象類型是否被忽略?

您對Java的工作方式存在誤解。這兩個報表的運行時間評估

List<POJO> pojoList = mapper.readValue(s, List.class); 
mapper.readValue(s, List.class); 

是完全一樣的。換句話說,分配的變量在運行時不起作用。在編譯時,所有它的好處是可能爲泛型提供上下文,並且poly expressions

當你調用你

mapper.readValue(s, List.class); 

你告訴傑克遜的JSON反序列化到一個List。而已。你沒有提供其他信息。傑克遜絕對沒有辦法猜測你是指POJO或其他任何東西的名單。因此,傑克遜猜測並使用自己的默認設置。對於JSON對象,該默認值是LinkedHashMap

更重要的是,List.class計算結果爲Class<List>,因此您readValue的返回類型是原始List類型。在處理原始類型時,泛型會被刪除。因此,您不會收到編譯錯誤,但您應該對未經檢查的轉換髮出警告。

你應該閱讀


在另一方面,這

List<POJO> pojoList = mapper.readValue(s, new TypeReference<List<POJO>>() {}); 

的作品,因爲你給傑克遜所有的,它需要正確地反序列化信息JSON。它是POJO元素(JSON對象)的List(JSON數組)。

但是,這有其自身的問題。 readValue的返回類型(即編譯時間)是從上下文(我之前提到)中推斷出來的,並且綁定到List<POJO>,因爲這是您要將結果分配給的表達式的類型。 TypeReference這裏沒有提供泛型的類型信息。正因爲如此,你可以做點像

List<String> stringList = mapper.readValue(s, new TypeReference<List<POJO>>() {}); 

它會編譯沒有錯誤。但在運行時,一切都可能會中斷。