2011-02-14 73 views
7

我想將字符串{"a": 1.0}讀作通用Java對象,同時保持相同的字符串格式。但是,當我嘗試時,傑克遜自動將內部表示更改爲{a = 1}。換句話說,我如何得到下面的代碼來打印{"a": 1.0}而不是{a = 1}?請注意,我必須將其作爲Object讀取(由於其他程序限制)。傑克遜與Java中的通用對象序列化

import org.codehaus.jackson.map.ObjectMapper; 

public class Main { 

    public static void main(String[] args) { 
     try 
    { 
      ObjectMapper mapper = new ObjectMapper(); 
      Object myObject = mapper.readValue("{\"a\": 1.0}", Object.class); 
      System.out.println(myObject.toString());    
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
     System.err.println(e.getMessage()); 
    } 
    } 

} 
+2

這對我沒有意義。對象沒有關鍵字「a」的任何屬性,那麼它如何被讀入?你不需要用這個屬性創建一個類嗎? – 2011-02-14 16:44:24

+1

也許他假設傑克遜以某種方式心靈感應地指出預期的類型...實際發生的是類型Object.class對Jackson有特殊的處理:它會創建映射,列表和包裝類型的「自然」映射(這些都是明顯的對象) – StaxMan 2011-02-14 20:06:10

回答

3

您需要一個匹配所需json結構的現有類。對象不是這樣的類。您仍然可以稱其爲Object,如果這是需要的:

Object myObject = mapper.readValue("{\"a\": 1.0}", SomeClass.class); 
2

如果您使用調試器,你會看到,返回的對象的類型是LinkedHashMap。所以你看到的是LinkedHashMap.toString()的輸出。有沒有辦法讓傑克遜改變這種狀況,所以你可以將它轉換爲一個地圖和自己創建的字符串或要求產生的JSON字符串你另一個返回類型:

if(myObject instanceof Map<?, ?>){ 
    final Map<?, ?> map = (Map<?, ?>) myObject; 
    final StringBuilder sb = new StringBuilder("{"); 
    boolean first = true; 
    for(final Entry<?, ?> entry : map.entrySet()){ 
     if(first){ 
      first = false; 
     } else{ 
      sb.append(","); 
     } 
     sb.append("\n\t'") 
      .append(entry.getKey()) 
      .append("':'") 
      .append(entry.getValue()) 
      .append("'"); 
    } 
    if(!first){ 
     sb.append("\n"); 
    } 
    sb.append("}"); 
    System.out.println(sb.toString()); 

} else{ 
    System.out.println(myObject); 
} 

輸出:

{ 
    'a':'1.0' 
} 
2

當Jackson被告知將JSON綁定到Object.class時,它就是這樣做的;但由於它不知道該JSON中可能存在什麼(或者可能想要使用哪些類),它必須使用大多數基本的Java類型:地圖,列表,數字,布爾值和字符串。所以任何JSON對象都由Map來表示; JSON Array by List,等等。

如果你想要一個自定義對象,你必須指定它的類型;或者在序列化時啓用包含顯式類型信息(「多態類型處理」)。這將添加類名稱或類型名稱,並可用於反序列化爲確切類型。

要做到這一點,任何類型的自身(或其超類型之一)必須使用@JsonTypeInfo註釋;或者,如果它是一個Object屬性,@JsonTypeInfo屬性(字段或方法)。

7

創建的對象將是一個地圖(如其他評論),因此它的toString產生你所看到的,{a = 1}。爲了讓您的代碼打印的東西更接近你的輸入值,你需要使用傑克遜將它寫回的東西,如:

System.out.println(mapper.writeValueAsString(myObject)); 

這給了我什麼,我相信你正在尋找:

{"a":1.0} 

換句話說,傑克遜已經將你的輸入字符串反序列化爲一個任意的Java對象。當您在對象上調用toString時,當然會使用它自己的toString。這可以寫出對象,但它喜歡,包括使用從Object的方法。要重現輸入字符串,您必須使用Jackson將對象序列化回去。