2016-01-24 85 views
2

我試圖讓我的腦袋圍繞convertValue方法傑克遜。起初,我認爲這將有點相當於Gson#fromJson方法,但似乎並非如此。傑克遜convertValue問題 - 替代?

這裏的問題:

// Map<String, Object> map = ... 
ObjectMapper mapper = new ObjectMapper(); 
MyPojo pojo = mapper.convertValue(map.get(key), MyPojo.class); 
for (Map.Entry<String, Object> m : map.entrySet()) { 
    System.out.println("k=" + m.getKey() + " v=" + m.getValue()); 
} 
pojo.name = "Banana"; 
for (Map.Entry<String, Object> m : map.entrySet()) { 
    System.out.println("k=" + m.getKey() + " v=" + m.getValue()); 
} 

輸出

k=66e8c013 v=MyPojo{name='Apple'} 
k=66e8c013 v=MyPojo{name='Banana'} 

注:代碼和輸出已被剝離到相關部分

所以,如果我修改我的pojo對象,它也越來越c掛在原始Map。對我來說,好像傑克遜不會在內部調用「new MyPojo()」,然後爲每個找到的變量設置值。

我能做些什麼來防止這種情況發生?有其他方法嗎?我是否需要創建一個複製構造函數才能獲得一個真正的新對象,而無需引用Map中的值?
此外,如果有人能告訴我什麼convertValue實際上做了什麼,這將是很酷。

+1

所以,你試圖將MyPojo轉換爲MyPojo?當你這樣做時,傑克遜將不會做任何事情:它只會返回原來的MyPojo,因爲不需要轉換任何東西。 –

+0

來源始終是您的代碼所用的最佳來源。 –

+0

@JBNizet不一定。通常這是一個'LinkedHashMap',在這種情況下,錯誤沒有發生。雖然看着調試器,但在這種特殊情況下你是對的 - 非常感謝。 – user3420815

回答

0

展望的convertValue代碼,你會發現

if (targetType != Object.class 
      && !toValueType.hasGenericTypes() 
      && targetType.isAssignableFrom(fromValue.getClass())) { 
     return fromValue; 
    } 

所以你的情況,如果map.get(key)MyPojo類型,則convertValue()方法確實返回參考輸入。這解釋了爲什麼當您更改「已轉換」對象時,地圖中的值會發生變化。

現在你的問題可以推斷出如何克隆一個對象,這是一個複雜的話題。

  • 如果您想要安全深度複製,您可以序列化和反序列化對象。然而,這個過程會帶來糟糕的表現。

  • 您可以實施clone()方法並標記類Cloneable,這是一種相當常見的解決方案,可以爲您提供控制和良好的性能。

  • 你也可以看看Apache Commons BeanUtils,它有cloneBean()方法,它使用getter和setter來克隆對象的屬性。

+0

感謝您的解釋和源代碼片段。我現在明白這個問題好得多。 – user3420815