2014-03-03 64 views
3

我有這樣一些類,所以:如何用Jackson反序列化泛型類?

@JsonIgnoreProperties(ignoreUnknown = true) 
@JsonSubTypes(
       { 
        @JsonSubTypes.Type(value = LionCage.class, name = "LION"), 
        @JsonSubTypes.Type(value = TigerCage.class, name = "TIGER"), 
       } 
      ) 
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") 
public abstract class Cage<ANIMAL> { 

    private AnimalType type; 
    private ANIMAL animal; 

} 

public enum AnimalType { 

    LION, TIGER 

} 

public LionCage extends Cage<Lion>{ 

    public LionCage(){ 
     super(AnimalType.LION); 
    } 
} 

public Lion { 

private int maneLength; 

} 

public class Zoo { 

    private List<Cage<?>> cages = new LinkedList<Cage<?>>(); 

} 

現在,如果我嘗試做以下操作:

String json = "{cages: [{\"type\": \"LION\", \"animal\": {\"maneLength\" : 10}}]}"; 

ObjectMapper om = new ObjectMapper(); 

Cage cage = om.readValue(json, Zoo.class); 

在籠子裏的第一個值應該是LionCage型的,它是。

問題是cages.get(0).getAnimal()返回LinkedHashMap如何才能使其返回正確的Animal子類?

我使用傑克遜1.

謝謝!

+0

你可以把你的getters和setters?問題是,cage.getAnimal()返回一個LinkedHashMap'這看起來很奇怪,因爲'animal'是一個'Animal'。 –

+0

@SotiriosDelimanolis它是'public Animal getAnimal()'。 「動物」不是一堂課。它是一個泛型「類型」,非常像'Map '中的'K'或'V'。 – Adam

+0

你完全正確,錯過了'Animal'作爲類型變量。 –

回答

4

對於您的List問題,這是您想要使用原始類型的一次。聲明Cage類型參數爲raw,而不是使用通配符進行參數化。

public class Zoo { 

    private List<Cage> cages = new LinkedList<Cage>(); 
    // ... getters and setters similarly 
} 

通過通配符,你告訴傑克遜,這並不重要,因此它使用它的默認,LinkedHashMap。如果您刪除通配符並使用原始類型,則需要在其他地方尋找提示。在這種情況下,它將查看它使用的實際的Cage實施。


你的JSON應該是這樣的

String json = "{\"type\": \"LION\", \"animal\": {\"maneLength\" : 10}}"; 

傑克遜將能夠確定的是,animalLion

通過type就會知道這是一個LionCage並通過

public LionCage extends Cage<Lion>{ 

類定義時它會知道的任何類型的引用變量Animal實際上應該是一個Lion

我對傑克遜2.

但它與傑克遜1的工作爲好。下面

import org.codehaus.jackson.annotate.JsonIgnoreProperties; 
import org.codehaus.jackson.annotate.JsonSubTypes; 
import org.codehaus.jackson.annotate.JsonTypeInfo; 
import org.codehaus.jackson.map.ObjectMapper; 

public class Example { 

    public static void main(String[] args) throws Exception { 
     String json = "{\"type\": \"LION\", \"animal\": {\"maneLength\" : 10}}"; 

     ObjectMapper om = new ObjectMapper(); 

     Cage cage = om.readValue(json, Cage.class); 
     System.out.println(cage.getClass()); 
     System.out.println(cage.getAnimal()); 

     System.out.println(((Lion) cage.getAnimal()).getManeLength()); 
    } 
} 

class Lion { 

    private int maneLength; 

    public int getManeLength() { 
     return maneLength; 
    } 

    public void setManeLength(int maneLength) { 
     this.maneLength = maneLength; 
    } 
} 

class LionCage extends Cage<Lion> { 

    public LionCage() { 
     super(AnimalType.LION); 
    } 
} 

class Tiger { 
} 

class TigerCage extends Cage<Tiger> { 

    public TigerCage() { 
     super(AnimalType.TIGER); 
    } 
} 

@JsonIgnoreProperties(ignoreUnknown = true) 
@JsonSubTypes({ @JsonSubTypes.Type(value = LionCage.class, name = "LION"), 
     @JsonSubTypes.Type(value = TigerCage.class, name = "TIGER"), }) 
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") 
abstract class Cage<Animal> { 

    public Cage(AnimalType type) { 
     this.setType(type); 
    } 

    public AnimalType getType() { 
     return type; 
    } 

    public void setType(AnimalType type) { 
     this.type = type; 
    } 

    public Animal getAnimal() { 
     return animal; 
    } 

    public void setAnimal(Animal animal) { 
     this.animal = animal; 
    } 

    private AnimalType type; 
    private Animal animal; 
} 

enum AnimalType { 
    LION, TIGER; 
} 

打印

class com.spring.LionCage 
[email protected] 
10 
+0

這就是我的JSON的外觀。傑克遜確實*不*正確deserielize它。試試看。 – Adam

+0

@Adam它適用於我。傑克遜2.你在1嗎? –

+0

我在第1版。 – Adam

3

代碼,我想你應該通過刪除不必要的類型和使用JsonTypeInfo.As.EXTERNAL_PROPERTY代替JsonTypeInfo.As.PROPERTY簡化您的解決方案。通過JsonTypeInfo.As.EXTERNAL_PROPERTY,您不必創建Cage子類。你根本不需要創建AnimalType。您POJO類看起來是這樣的:

@JsonIgnoreProperties(ignoreUnknown = true) 
class Cage<ANIMAL> { 

    @JsonSubTypes({ 
     @JsonSubTypes.Type(value = Lion.class, name = "LION"), 
     @JsonSubTypes.Type(value = Tiger.class, name = "TIGER") 
    }) 
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type") 
    private ANIMAL animal; 

    public ANIMAL getAnimal() { 
     return animal; 
    } 

    public void setAnimal(ANIMAL animal) { 
     this.animal = animal; 
    } 

    @Override 
    public String toString() { 
     return "Cage [animal=" + animal + "]"; 
    } 
} 

class Lion { 

    private int maneLength; 

    public int getManeLength() { 
     return maneLength; 
    } 

    public void setManeLength(int maneLength) { 
     this.maneLength = maneLength; 
    } 

    @Override 
    public String toString() { 
     return "Lion [maneLength=" + maneLength + "]"; 
    } 
} 

class Tiger { 

    private int length; 

    public int getLength() { 
     return length; 
    } 

    public void setLength(int length) { 
     this.length = length; 
    } 

    @Override 
    public String toString() { 
     return "Tiger [maneLength=" + length + "]"; 
    } 
} 

簡單的用法:

String jsonLion = "{\"type\": \"LION\", \"animal\": {\"maneLength\" : 10}}"; 
String jsonTiger = "{\"type\": \"TIGER\", \"animal\": {\"length\" : 11}}"; 

ObjectMapper om = new ObjectMapper(); 

System.out.println(om.readValue(jsonLion, Cage.class)); 
System.out.println(om.readValue(jsonTiger, Cage.class)); 

以上代碼打印:

Cage [animal=Lion [maneLength=10]] 
Cage [animal=Tiger [maneLength=11]] 

我沒有Jackson 1.X但我希望我的測試解決方案它會爲你工作。

相關問題