繁体   English   中英

如何用Jackson反序列化泛型类?

[英]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}}";

杰克逊将能够确定该animalLion

通过该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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM