81

我正在使用 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;

有人可以帮我吗?

4

8 回答 8

59

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

在stackoverflow上看到这个答案:杰克逊JSON库:如何实例化一个包含抽象字段的类

也许还可以看到杰克逊多态反序列化

于 2012-10-05T18:23:53.103 回答
10

反序列化时需要使用具体类而不是抽象类。如果 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
    }
于 2020-06-10T09:03:54.870 回答
6

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

于 2012-10-06T18:54:51.130 回答
3

对我来说,没有为我尝试使用的 POJO 定义默认构造函数。创建默认构造函数修复了它。

public class TeamCode {

    @Expose
    private String value;

    public String getValue() {
        return value;
    }

    **public TeamCode() {
    }**

    public TeamCode(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "TeamCode{" +
                "value='" + value + '\'' +
                '}';
    }

    public void setValue(String value) {
        this.value = value;
    }

}
于 2020-01-28T19:09:38.083 回答
3

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

@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实例。

于 2020-11-23T22:10:17.073 回答
1

我单独使用 lombok@Data@Builder注释时遇到了这个问题,我将其替换为:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder

它解决了我的问题。

于 2021-12-07T14:25:55.760 回答
0

使用 lombok 注释。

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

    @Builder.Default
    @JsonProperty("id")
    String id = "";
}
于 2021-07-06T18:20:46.257 回答
0

采用@JsonDeserialize(contentAs= ConcreteCLass.class)

于 2021-08-02T13:51:02.687 回答