2012-09-10 72 views
0

我在寫一個使用傑克遜序列化/反序列化對象的類。在編譯時,我不知道哪個是我要序列化/反序列化的對象的類型。傑克遜 - 反序列化到運行時指定的類

我讀了幾篇有關TypeReferenceTypeFactory的使用情況的文章和問題,但是我仍然遇到一些問題。

我的類是什麼樣子(去掉了一些不相關的代碼):

public class JsonSerializer<T> { 

    private ObjectMapper objectMapper; 
    private TypeReference typeReference; 

    @PostConstruct 
    public void init() { 
     objectMapper = new ObjectMapper(); 
     typeReference = new TypeReference<T>(){ }; 
    } 

    // ... 


    public Object decode(CachedData cachedData) { 
    try { 
     return objectMapper.readValue(cachedData.getData(), typeReference); 
    } // ... 
    } 
} 

這是我使用來測試此的代碼片段:

public class SerializerTest { 

    private JsonSerializer<Clazz> serializer; 
    private ObjectMapper objectMapper = new ObjectMapper(); 
    private static final String CHARSET = "UTF-8"; 
    private Clazz data = generateData(); // creates a simple object 

    @BeforeMethod 
    public void beforeMethod() { 
     serializer = new JsonSerializer<Clazz>(); 
     serializer.init(); 
    } 

    // ... 

    public void shouldDecodeDataCorrectly() throws Exception { 
    CachedData cachedData = new CachedData(0, 
     objectMapper.writeValueAsString(data).getBytes(CHARSET), 
     CachedData.MAX_SIZE); 

    Object object = serializer.decode(cachedData); 
    assertEquals(data, object); 
    } 

    public static class Clazz { 
    // POJO with getters and setters 
    } 

} 

至於我能理解,使用typeReference應該足以讓知道解串行器從字節流中讀取的值應放在Clazz對象中。但是,decode()方法返回的對象仍然是Map,我知道它是反序列化的默認類。

我也嘗試改變decode()方法返回return objectMapper.readValue(cachedData.getData(), objectMapper.getTypeFactory().constructType(typeReference)),但我遇到了同樣的問題。

我很確定這是關於我將類型傳入序列化程序的方式,但至今尚未解決。謝謝。

+0

請參閱http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type – lisak

回答

1

目前尚不十分清楚你到底在做什麼:大部分代碼都沒有改變。具體使用TypeReference是錯誤的:你不能使用類型變量,類型必須是具體的。

但是,解決方案可能比您想象的要簡單。如果您可以跟蹤原始Class,只需存儲該名稱(或從clazz.getName()起的名稱),並在反序列化時傳遞該名稱。

+0

這是Couchbase的'Transcoder'實現,它是一種序列化/反序列化數據的方法然後將它們放入緩存中。我使用Jackson將JSON序列化/反序列化爲String,然後將其轉換爲byte []並放入一個'CachedData'對象。我嘗試將Clazz.class對象傳入'Serializer'並將調用改爲'objectMapper.readValue(cachedData.getData(),clazz);',但它仍然不起作用 - 我將更新該問題。 – manub

+0

它現在工作 - 我不得不刪除我之前添加的默認打字配置(在我發佈問題後)。謝謝! – manub

0

您是否檢查@JsonTypeInfo?請看看它的文檔。

+0

我不能註釋類 - 我認爲應該有另一個告訴'ObjectMapper'使用特定類反序列化的方法? – manub

0

基於在http://jackson.codehaus.org/1.9.9/javadoc/org/codehaus/jackson/type/TypeReference.html 這裏的Javadoc是我會怎麼做:

從JsonSerializer

取出typeReference場修改JsonSerializer.decode方法採取引用類型作爲參數

傳遞類型參數作爲參數

Object object = transcoder.decode(cachedData, new TypeReference<Clazz>() {}); 

BTW - 「transcoder 「應該是」序列化器「?錯字?

+0

雖然合法使用,但在這裏使用'TypeReference'是不必要的。而應該直接傳遞'Clazz.class'。只有當你需要爲像'Map '這樣的東西指定泛型類型參數時'TypeReference'纔有用。 – StaxMan

+0

我無法更改該方法的簽名,但是我可以通過類Clazz的Class對象。儘管如此,仍然沒有工作,請看看其他評論。(是的,序列化程序和代碼轉換器是相當的,當我提出這個問題時我改變了代碼,我忘了在所有地方改變它) – manub