[英]How to deserialize generic classes with 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。
谢谢!
对于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
我想你应该通过删除不必要的类型和使用简化的解决方案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测试我的解决方案,但我希望它对你有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.