我正在使用 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
我在属性方面遇到问题:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "@id")
@JsonSubTypes({ @JsonSubTypes.Type(value = MyAbstractClass.class, name = "MyAbstractClass") })
@ManyToOne
private MyAbstractClass object;
有人可以帮助我吗?
你不能实例化一个抽象类,杰克逊也不能。 您应该向 Jackson 提供有关如何使用具体类型实例化 MyAbstractClass 的信息。
在 stackoverflow 上查看这个答案:Jackson JSON 库:如何实例化包含抽象字段的类
也许还可以看到杰克逊多态反序列化
我单独使用 lombok 的
@Data
和 @Builder
注释时遇到了这个问题,我将其替换为:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
它解决了我的问题。
反序列化时需要使用具体类而不是抽象类。 如果抽象类有多个实现,那么在这种情况下,您可以按如下方式使用它 -
@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
}
您的
@JsonSubTypes
声明没有意义:它需要列出实现(子)类,而不是类本身(这将毫无意义)。因此,您需要修改该条目以列出子类;或者使用其他机制来注册子类(SimpleModule
有类似addAbstractTypeMapping
之类的东西)。
对于我来说,没有为我尝试使用的 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;
}
}
在您的具体示例中,问题是您没有正确使用此构造:
@JsonSubTypes({ @JsonSubTypes.Type(value = MyAbstractClass.class, name = "MyAbstractClass") })
@JsonSubTypes.Type
应包含抽象类的实际非抽象子类型。
因此,如果您有:
abstract class Parent
和具体子类
Ch1 extends Parent
和
Ch2 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
实例。
使用
@JsonDeserialize(contentAs= ConcreteCLass.class)
设置默认构造函数有助于解决问题
使用lombok注释。
@AllArgsConstructor
@NoArgsConstructor
@Builder
@JsonPropertyOrder({"name", "id"})
public class CreationUser {
@Builder.Default
@JsonProperty("name")
String name = "";
@Builder.Default
@JsonProperty("id")
String id = "";
}
使用 lombok 我遇到了同样的问题,我尝试过这个来解决
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
我有这个接口,由Spring Data JPA使用,用于投影:
public interface xxxProjection {
杰克逊确实不知道如何反序列化/构造对象。
@JsonDeserialize(as = xxxProjectionImpl.class)
public interface xxxProjection {
String getkey();
String getValue();
}
@Getter
class xxxProjectionImpl implements xxxProjection {
private String key;
private String value;
}