gpt4 book ai didi

java - jackson 多态性: Nested Subtypes

转载 作者:行者123 更新时间:2023-11-30 01:40:54 25 4
gpt4 key购买 nike

是否可以以嵌套方式使用多个@JsonSubType注释?

例如,想象以下类:

@Data
@JsonSubTypeInfo(include=As.EXISTING_PROPERTY, property="species", use=Id.NAME, visible=true)
@JsonSubTypes({
@Type(name="Dog", value=Dog.class)
@Type(name="Cat", value=Cat.class)
})
public abstract class Animal {
private String name;
private String species;
}
@Data
@JsonSubTypeInfo(include=As.EXISTING_PROPERTY, property="breed", use=Id.NAME, visible=true)
@JsonSubTypes({
@Type(name="Labrador", value=Labrador.class)
@Type(name="Bulldog", value=Bulldog.class)
})
public abstract class Dog extends Animal {
private String breed;
}
@Data
public class Cat extends Animal {
private boolean lovesCatnip;
}
@Data
public class Labrador extends Dog {
private String color;
}
@Data
public class Bulldog extends Dog {
private String type; // "frenchy", "english", etc..
}

如果我使用对象映射器,我可以成功地将 Bulldog 映射到 JSON,但是,当尝试读取生成的 JSON 并将其读回时,我会收到如下错误:

Can not construct instance of com.example.Dog abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

是否有可能让 jackson 使用这样的子类型?我需要为每个子类创建一个自定义反序列化器吗?

编辑:

我对原来的帖子稍作修改了上面的类。我添加了一个 Cat 类,并让该类和 DogAnimal 扩展。

以下是可以使用 ObjectMapper::writeValueAsString 创建的示例 JSON:

{
"name": null,
"species": "Dog",
"breed": "Bulldog",
"type": "B-Dog"
}

最佳答案

如果我使用 @JsonTypeInfo 和与您类似的设置,则以下内容有效。也许你的问题出在你的反序列化代码中,所以看看这个:

public class MyTest {

@Test
public void test() throws IOException {
final Bulldog bulldog = new Bulldog();
bulldog.setBreed("Bulldog");
bulldog.setType("B-Dog");

final ObjectMapper om = new ObjectMapper();
final String json = om.writeValueAsString(bulldog);
final Dog deserialized = om.readValue(json, Dog.class);
assertTrue(deserialized instanceof Bulldog);

}

@JsonTypeInfo(include = As.EXISTING_PROPERTY, property = "species", use = Id.NAME, visible = true)
@JsonSubTypes({
@Type(name = "Dog", value = Dog.class),
@Type(name = "Cat", value = Cat.class)
})

public static abstract class Animal {

private String name;
private String species;
}

@JsonTypeInfo(include = As.EXISTING_PROPERTY, property = "breed", use = Id.NAME, visible = true)
@JsonSubTypes({
@Type(name = "Labrador", value = Labrador.class),
@Type(name = "Bulldog", value = Bulldog.class)
})
public static abstract class Dog {

private String breed;

public String getBreed() {
return breed;
}

public void setBreed(final String breed) {
this.breed = breed;
}
}

public static abstract class Cat {

private String name;
}

public static class Labrador extends Dog {

private String color;

public String getColor() {
return color;
}

public void setColor(final String color) {
this.color = color;
}
}

public static class Bulldog extends Dog {

private String type; // "frenchy", "english", etc..

public String getType() {
return type;
}

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

针对更新的问题进行了编辑:如果您可以对继承层次结构使用相同的属性(在以下代码中为隐藏属性“@class”),则它可以工作:

    @Test
public void test() throws IOException {
final Bulldog bulldog = new Bulldog();
// bulldog.setSpecies("Dog");
// bulldog.setBreed("Bulldog");
bulldog.setType("B-Dog");

final ObjectMapper om = new ObjectMapper();
final String json = om.writeValueAsString(bulldog);
final Animal deserialized = om.readValue(json, Animal.class);
assertTrue(deserialized instanceof Bulldog);

}

@JsonTypeInfo(include = As.PROPERTY, use = Id.CLASS, visible = false)
@JsonSubTypes({
@Type(Dog.class),
@Type(Cat.class)
})
public static abstract class Animal {

}

@JsonTypeInfo(include = As.PROPERTY, use = Id.CLASS, visible = false)
@JsonSubTypes({
@Type(name = "Labrador", value = Labrador.class),
@Type(name = "Bulldog", value = Bulldog.class)
})
public static abstract class Dog
extends Animal {

}

如果您想设置动物类型(例如计算物种、品种等),您也可以使用此设置:

@Test
public void test() throws IOException {
final Bulldog bulldog = new Bulldog();
bulldog.setAnimalType("Bulldog");
// bulldog.setSpecies("Dog");
// bulldog.setBreed("Bulldog");
bulldog.setType("B-Dog");

final ObjectMapper om = new ObjectMapper();
final String json = om.writeValueAsString(bulldog);
System.out.println(json);
final Animal deserialized = om.readValue(json, Animal.class);
assertTrue(deserialized instanceof Bulldog);

}

@JsonTypeInfo(include = As.EXISTING_PROPERTY, property = "animalType", use = Id.NAME, visible = true)
@JsonSubTypes({
@Type(Dog.class)
})
public static abstract class Animal {

private String animalType;

public String getAnimalType() {
return animalType;
}

public void setAnimalType(final String animalType) {
this.animalType = animalType;
}
}

@JsonTypeInfo(include = As.EXISTING_PROPERTY, property = "animalType", use = Id.NAME, visible = true)
@JsonSubTypes({
@Type(value = Bulldog.class)
})
public static abstract class Dog
extends Animal {

}

@JsonTypeName("Bulldog")
public static class Bulldog extends Dog {

private String type; // "frenchy", "english", etc..

public String getType() {
return type;
}

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

关于java - jackson 多态性: Nested Subtypes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60055489/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com