杰克逊用子类反序列化

Sno*_*irl 3 java json jackson

好吧,我知道有很多类似的问题,但似乎没有任何效果.

我为我的实体设置了以下结构.

public abstract class MyAbstractClass {
   // bunch of properties, getters, and setters that subclasses share

   public abstract String getType();
}

public class MySubclass1 extends MyAbstractClass {
    //  a few unique properties, getters, and setters

    public String getType() {
        return "Type_1"; //always the same for each instance of MySubclass1
    }
}

public class MySubclass2 extends MyAbstractClass {
    //  a few unique properties, getters, and setters

    public String getType() {
        return "Type_2"; //always the same for each instance of MySubclass2
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的控制器中,我尝试将请求映射到以下方法.

public @RequestBody MyAbstractClass saveObject(@RequestBody MyAbstractClass mac) {
    // call model to save object
}
Run Code Online (Sandbox Code Playgroud)

我想使用1个控制器方法而不是2个实体的单独控制器方法.但是使用以上结果如下.

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of path.to.my.entity.MyAbstractClass, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
Run Code Online (Sandbox Code Playgroud)

说得通.

尝试1

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="implementingClass")
public abstract class MyAbstractClass
Run Code Online (Sandbox Code Playgroud)

我认为它做了 - 添加了一个implementingClass将存储子类的元数据属性.

结果如何.

Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'implementingClass' that is to contain type id  (for class path.to.my.entity.MyAbstractClass)
Run Code Online (Sandbox Code Playgroud)

尝试用"class"而不是"implementClass" property获得类似的结果.

尝试2

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
    @Type(name="MySubclass1", value=MySubclass1.class),
    @Type(name="MySubclass2", value=MySubclass2.class)
})
public abstract class MyAbstractClass
Run Code Online (Sandbox Code Playgroud)

我认为它做什么 - 使用定义name来做某种包装的东西.

结果如何.

Could not resolve type id 'myUuid' into a subtype of [simple type, class path.to.my.entity.MyAbstractClass]
Run Code Online (Sandbox Code Playgroud)

即使添加@JsonTypeName("MySubclass1")@JsonTypeName("MySubclass2")2个子类,结果也相同.

其他尝试

我尝试了很多.什么都行不通.这里不包括所有内容.

我觉得应该有一个简单的方法来做到这一点,但我只是继续错误地配置.

我觉得getType可以利用它,但我不想为类型添加实际属性(它只是一个帮助方法).另外,我想用注释与其他选项来做这件事.

谢谢.

Sno*_*irl 6

我想出来但我想我会回答以防其他人有这个问题.

type在子类中添加了一个属性,而不仅仅是一个辅助方法(下面包含一个例子).

public class MySubclass1 extends MyAbstractClass {
    @Transient
    private final String type = "TYPE_1";

    public String getType() {
        return type;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我为我的抽象超类做了以下事情.

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type")
@JsonSubTypes({
    @Type(name="TYPE_1", value=MySubclass1.class),
    @Type(name="TYPE_2", value=MySubclass2.class)
})
public abstract class MyAbstractClass
Run Code Online (Sandbox Code Playgroud)

提供JSON时,我肯定会包含该类型.我不会包括这个,因为它是奇怪的淘汰疯狂.

这不是很好.但它奏效了.