【问题标题】:Jackson Deserialize with SubclassesJackson 使用子类反序列化
【发布时间】:2015-10-14 20:10:46
【问题描述】:

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

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

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
    }
}

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

public @RequestBody MyAbstractClass saveObject(@RequestBody MyAbstractClass mac) {
    // call model to save object
}

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

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

有道理。

试一试

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

我认为它的作用是添加一个元数据implementingClass 属性来存储子类。

结果是什么。

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

property 尝试使用“class”而不是“implementingClass”,得到了类似的结果。

试试 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

我认为它的作用 - 使用定义的 name 来做某种包装的事情。

结果是什么。

Could not resolve type id 'myUuid' into a subtype of [simple type, class path.to.my.entity.MyAbstractClass]

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

其他尝试

我尝试了很多。没有任何效果。不会在这里包括所有内容。

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

我觉得getType 可能会被利用,但我不想为类型添加实际属性(它只是一个辅助方法)。我也想用注释和其他选项来做到这一点。

谢谢。

【问题讨论】:

  • 你能举一个你提交给控制器的 JSON 的例子吗?对于您的TRY 1,您告诉它在序列化中添加“implementingClass”,并在反序列化时查找“implementingClass”属性,但您没有指定它。 See also
  • 好的,这回答了一些问题。我不想为 JSON 实现 implementationClass。所以也许 Try 1 不是我想做的。泰
  • 所以这可能归结为是否可以利用getType。我认为它不能成为实际财产。
  • 您想如何利用getType?它是 JSON 中的属性吗?如果是这样,只需将“implementingClass”更改为“type”,并使用@JsonSubTypes(如TRY 2)与例如@Type(name="Type_1", value=MySubclass1.class)。同样,如果我们知道 JSON 的样子,那就容易多了。

标签: java json jackson


【解决方案1】:

我想通了,但我想我会回答,以防其他人有这个问题。

我向我的子类添加了一个 type 属性,而不仅仅是一个辅助方法(下面包含一个示例)。

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

    public String getType() {
        return type;
    }
}

然后我为我的抽象超类做了以下操作。

@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

在提供 JSON 时,我确定要包含类型。我不会包括这个,因为它是奇怪的淘汰赛精神错乱。

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

【讨论】:

  • 为什么我会收到错误@Transient' not applicable to field
猜你喜欢
  • 2016-08-05
  • 1970-01-01
  • 2016-04-20
  • 2012-07-24
  • 1970-01-01
  • 1970-01-01
  • 2012-10-18
相关资源
最近更新 更多