2013-01-04 106 views
3

我有下面的示例類:傑克遜反序列多態類型

class Zoo { 
    public Collection<? extends Animal> animals; 
} 

當序列化,我想通過做連載不亞於類型的信息,我可以:

mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 

而我得到以下JSON:

[ 
    "com.bp.samples.json.generics.Zoo", 
    { 
     "animals": [ 
      "java.util.ArrayList", 
      [ 
       [ 
        "com.bp.samples.json.generics.Bird", 
        { 
         "name": "bird-1", 
         "wingSpan": "6 feets", 
         "preferredFood": "food-1" 
        } 
       ], 
       [ 
        "com.bp.samples.json.generics.Cat", 
        { 
         "name": "cat-1", 
         "favoriteToy": "toy-1" 
        } 
       ], 
       [ 
        "com.bp.samples.json.generics.Dog", 
        { 
         "name": "dog-1", 
         "breed": "bread-1", 
         "leashColor": "black" 
        } 
       ] 
      ] 
     ] 
    } 
] 

當談到反序列化,努力做到:

mapper.readValue(new File("./DataFiles/Zoo-2.json"), Zoo.class); 

導致以下異常:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: 
Can not deserialize instance of com.bp.samples.json.generics.Zoo out of START_ARRAY toke 

,努力做到:

mapper.readValue(new File("./DataFiles/Zoo-2.json"), 
    new TypeReference<Collection<? extends Animal>>() {}); 

結果:

Can not construct instance of com.bp.samples.json.generics.Animal, 
problem: abstract types either need to be mapped to concrete types, have custom 
deserializer, or be instantiated with additional type information 
at [Source: ./DataFiles/Zoo-2.json; line: 2, column: 5] 

編寫自定義解串器,斷當然,解決了這個問題,但是在那裏去了ialize沒有自定義反序列化器?

謝謝,你啓用類型的信息爲你使用反序列化ObjectMapper實例 Behzad

+0

將JSON數組(集合)反序列化爲Java對象(Zoo - 不是集合)將不起作用(沒有特殊處理)。你必須使用DefaultTyping來提供類型信息嗎?您可能想要查看完整的多態反序列化示例http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html –

+0

我建議您選擇一個標記來替換java(以獲取這個問題更多關注)。 –

+0

@Programmer_Bruce我想這裏的數組是由於默認的類型信息包含,所以應該沒問題。 – StaxMan

回答

1

製作河畔。你想反序列化爲Zoo而不是動物集合,所以第一個snipet代碼是正確的。您可能還想嘗試Genson lib。 我剛剛檢查過你的例子,並且一切似乎都正常。 要啓用Genson多態類型的支持,你需要配置genson實例:

Genson genson = new Genson.Builder().setWithClassMetadata(true).create(); 
2

你首先應該試圖就我所看到的工作。我能想到的唯一解釋是你試圖使用不同配置的ObjectMapper進行反序列化:兩者都必須以相同的方式啓用默認類型(因爲這是控制是否包含類型信息)。

如果您使用的是相同的映射器實例(或完全相同的配置),您可能需要提交錯誤報告,以便診斷並修復問題。

+0

謝謝大家的答案。我只是認爲,在反序列化時,它應該看到類型信息並在沒有啓用的情況下使用它。所以,無論如何,當我反序列化時,我想:「mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL)」。謝謝你 –

+0

不,沒有可靠的方法來知道任意的JSON對象或數組是否代表Java對象或類型信息包裝 - 並且由於含糊不清,設置必須匹配。 – StaxMan