无法构建 - 杰克逊的实例

Dan*_* M. 44 java jackson

我正在使用杰克逊,我遇到了问题,当我尝试反序列化一个对象时,我收到以下错误:

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
Run Code Online (Sandbox Code Playgroud)

我在属性中遇到问题:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "@id")
@JsonSubTypes({ @JsonSubTypes.Type(value = MyAbstractClass.class, name = "MyAbstractClass") })
@ManyToOne
private MyAbstractClass object;
Run Code Online (Sandbox Code Playgroud)

谁能帮助我?

jla*_*edo 41

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

请参阅stackoverflow上的这个答案:Jackson JSON库:如何实例化包含抽象字段的类

也许还可以看到Jackson Polymorphic Deserialization

  • 感谢您的帮助,我解决了:`JsonTypeInfo.Id.NAME,include = JsonTypeInfo.As.PROPERTY,property ="class")``property ="class"`,来自我的JSON,告知子类将是什么用过的. (2认同)
  • 感谢您提供参考:@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,include = JsonTypeInfo.As.PROPERTY,property =“ @class”)可以解决问题。就像JPA表的说明符值一样。谢谢。 (2认同)

Gab*_*ade 30

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

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
Run Code Online (Sandbox Code Playgroud)

它解决了我的问题。


小智 7

在反序列化时,您需要使用具体类而不是抽象类。如果 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
    }
Run Code Online (Sandbox Code Playgroud)


Sta*_*Man 6

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


ACV*_*ACV 5

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

@JsonSubTypes({ @JsonSubTypes.Type(value = MyAbstractClass.class, name = "MyAbstractClass") })
Run Code Online (Sandbox Code Playgroud)

@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")
})
Run Code Online (Sandbox Code Playgroud)

这里name应该匹配你的“鉴别器”的值:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, 
include = JsonTypeInfo.As.WRAPPER_OBJECT, 
property = "type")
Run Code Online (Sandbox Code Playgroud)

property字段中,这里它等于type。所以type将是键,您设置的值name将是值。

因此,当 json 字符串出现时,如果它具有以下形式:

{
 "type": "ch1",
 "other":"fields"
}
Run Code Online (Sandbox Code Playgroud)

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

如果您发送此信息:

{
 "type": "ch2",
 "other":"fields"
}
Run Code Online (Sandbox Code Playgroud)

你会得到一个Ch2实例。