下面是我理想的 json 文件和具体类的结构。 但我无法让它工作,而且替代方案会不太优雅。
测试 3 失败,出现以下错误:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Cannot construct instance of `com.org.DeserializationTest$InterfaceB`
(no Creators, like default constructor, exist):
abstract types either need to be mapped to concrete types,
have custom deserializer, or contain additional type information
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION`
disabled); line: 3, column: 5]
如有任何帮助,我们将不胜感激!
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static com.fasterxml.jackson.annotation.JsonTypeInfo.As.EXISTING_PROPERTY;
public class DeserializationTest {
final ObjectMapper om = new ObjectMapper();
@Test
void one() throws JsonProcessingException {
Assertions.assertInstanceOf(ConcreteClass2.class,
om.readValue("""
{
"typeA": "B",
"typeB": "B2"
}""", InterfaceB.class));
}
@Test
void two() throws JsonProcessingException {
Assertions.assertInstanceOf(ConcreteClass1.class,
om.readValue("""
{
"typeA": "A1"
}""", InterfaceA.class));
}
@Test
void three() throws JsonProcessingException {
Assertions.assertInstanceOf(ConcreteClass2.class,
om.readValue("""
{
"typeA": "B",
"typeB": "B2"
}""", InterfaceA.class));
}
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, include = EXISTING_PROPERTY,
property = "typeA"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = ConcreteClass1.class, name = "A1"),
@JsonSubTypes.Type(value = InterfaceB.class, name = "B")
})
public interface InterfaceA {
String getTypeA();
String getTypeB();
}
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, include = EXISTING_PROPERTY,
property = "typeB"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = ConcreteClass2.class, name = "B2"),
@JsonSubTypes.Type(value = ConcreteClass3.class, name = "B3")
})
public interface InterfaceB extends InterfaceA {
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class ConcreteClass1 implements InterfaceA {
@Override
public String getTypeA() {
return "A1";
}
@Override
public String getTypeB() {
return null;
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class ConcreteClass2 implements InterfaceB {
@Override
public String getTypeA() {
return "B";
}
@Override
public String getTypeB() {
return "B2";
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class ConcreteClass3 implements InterfaceB {
@Override
public String getTypeA() {
return "B";
}
@Override
public String getTypeB() {
return "B3";
}
}
}
ChatGPT 和当前的答案没有帮助:Jackson 多态性:嵌套子类型
有一些事情无法在您的代码中工作:在接口上使用
@JsonTypeInfo
并将 include
设置为 EXISTING_PROPERTY
,并且您的子类都不会显示无参数构造函数或创建者方法。
@JsonTypeInfo
界面上有 EXISTING_PROPERTY
当
include
设置为 EXISTING_PROPERTY
时,父类必须展示与 property
的 @JsonTypeInfo
属性中指定的同名属性。像这样,Jackson 可以根据 JsonSubTypes
注释中设置的值来区分子类实例。现在,由于接口不能具有属性,因此此配置无法工作。
您的子类没有任何默认构造函数或创建者方法。没有它们,Jackson 就无法创建实例并使用相应的 Json 值对其进行初始化。