我有一些类似的课程:
@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
子类?
我正在使用Jackson 1。
谢谢!
答案 0 :(得分:4)
对于您的List
问题,这是您想要使用原始类型的一次。将Cage
类型参数声明为raw,而不是使用通配符进行参数化。
public class Zoo {
private List<Cage> cages = new LinkedList<Cage>();
// ... getters and setters similarly
}
使用通配符,您告诉Jackson它没关系,所以它使用默认值LinkedHashMap
。如果删除通配符并使用原始类型,则需要在其他位置查找提示。在这种情况下,它将查看它使用的实际Cage
实现。
您的JSON应该如下所示
String json = "{\"type\": \"LION\", \"animal\": {\"maneLength\" : 10}}";
杰克逊将能够确定animal
是Lion
。
通过type
,它会知道它是LionCage
并通过
public LionCage extends Cage<Lion>{
它会知道对类型变量Animal
的任何引用实际上应该是Lion
。
我在杰克逊2上。
但它也适用于Jackson 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
com.spring.Lion@15d16efc
10
答案 1 :(得分:4)
我认为您应该通过删除不必要的类型并使用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测试我的解决方案,但我希望它对您有用。