无法构建 - 杰克逊的实例

时间:2012-10-05 16:50:57

标签: java jackson

我正在使用Jackson而且我遇到了问题,当我尝试反序列化一个Object时出现以下错误:

com.fasterxml.jackson.databind.JsonMappingException: 
    Can not construct instance of net.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.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "@id")
@JsonSubTypes({ @JsonSubTypes.Type(value = MyAbstractClass.class, name = "MyAbstractClass") })
@ManyToOne
private MyAbstractClass object;

有人可以帮助我吗?

7 个答案:

答案 0 :(得分:36)

你不能实例化抽象类,杰克逊也不能。 您应该向Jackson提供有关如何使用具体类型实例化MyAbstractClass的信息。

在stackoverflow上查看此答案:Jackson JSON library: how to instantiate a class that contains abstract fields

也许还可以看到Jackson Polymorphic Deserialization

答案 1 :(得分:6)

你的@JsonSubTypes声明没有意义:它需要列出实现(子)类,而不是类本身(这将是毫无意义的)。因此,您需要修改该条目以列出其中的子类;或使用其他一些机制来注册子类(SimpleModule有类似addAbstractTypeMapping)。

答案 2 :(得分:2)

反序列化时,需要使用具体类而不是Abstract类。 如果Abstract类具有多个实现,那么在这种情况下,您可以按以下方式使用它-

  @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
    @JsonSubTypes({ 
      @Type(value = Bike.class, name = "bike"), 
      @Type(value = Auto.class, name = "auto"), 
      @Type(value = Car.class, name = "car")
    })
    public abstract class Vehicle {
        // fields, constructors, getters, setters
    }

答案 3 :(得分:0)

对我来说,没有为我尝试使用的POJO定义默认的构造函数。创建默认的构造函数即可解决此问题。

mojave

答案 4 :(得分:0)

在您的具体示例中,问题在于您没有正确使用此构造:

@JsonSubTypes({ @JsonSubTypes.Type(value = MyAbstractClass.class, name = "MyAbstractClass") })

@JsonSubTypes.Type应该包含抽象类的实际非抽象子类型。

因此,如果您有:

abstract class Parent和具体的子类

Ch1 extends ParentCh2 extends Parent

然后您的注释应如下所示:

@JsonSubTypes({ 
          @JsonSubTypes.Type(value = Ch1.class, name = "ch1"),
          @JsonSubTypes.Type(value = Ch2.class, name = "ch2")
})

这里name应该与您的“标识符”的值匹配:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, 
include = JsonTypeInfo.As.WRAPPER_OBJECT, 
property = "type")

property字段中,它等于type。因此,type将成为键,而您在name中设置的值将成为值。

因此,当json字符串具有以下格式时:

{
 "type": "ch1",
 "other":"fields"
}

Jackson会将其自动转换为Ch1类。

如果您发送此邮件:

{
 "type": "ch2",
 "other":"fields"
}

您将获得一个Ch2实例。

答案 5 :(得分:0)

使用 lombok 注释。

@AllArgsConstructor
@NoArgsConstructor
@Builder
@JsonPropertyOrder({"name", "id"})
public class CreationUser {
    @Builder.Default
    @JsonProperty("name")
    String name = "";

    @Builder.Default
    @JsonProperty("id")
    String id = "";
}

答案 6 :(得分:0)

使用@JsonDeserialize(contentAs= ConcreteCLass.class)