杰克逊多态性问题,在给定的结构中,一个接口可以是另一个接口的子类型吗?

问题描述 投票:0回答:1

下面是我理想的 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 多态性:嵌套子类型

java jackson polymorphism
1个回答
0
投票

有一些事情无法在您的代码中工作:在接口上使用

@JsonTypeInfo
并将
include
设置为
EXISTING_PROPERTY
,并且您的子类都不会显示无参数构造函数或创建者方法。

@JsonTypeInfo
界面上有
EXISTING_PROPERTY

include
设置为
EXISTING_PROPERTY
时,父类必须展示与
property
@JsonTypeInfo
属性中指定的同名属性。像这样,Jackson 可以根据
JsonSubTypes
注释中设置的值来区分子类实例。现在,由于接口不能具有属性,因此此配置无法工作。

没有默认的构造函数或创建者方法

您的子类没有任何默认构造函数或创建者方法。没有它们,Jackson 就无法创建实例并使用相应的 Json 值对其进行初始化。

© www.soinside.com 2019 - 2024. All rights reserved.