You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Jackson注解反序列化Java抽象接口时遇实例创建错误求助

Jackson反序列化抽象接口报错排查与修复

问题场景

尝试使用Jackson注解对指定JSON做反序列化时,出现抽象类无法实例化的错误,相关代码与错误信息如下:

抽象接口 ServiceConfiguration

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME,
  include = JsonTypeInfo.As.PROPERTY,
  property = "serviceType")
@JsonSubTypes({
    @JsonSubTypes.Type(value = StripeServiceConfiguration.class, name = "Stripe"),
    @JsonSubTypes.Type(value = BrainServiceConfiguration.class, name = "Brain"),
})
public interface ServiceConfiguration {
  TypeOfService getServiceType();
}

StripeServiceConfiguration 实现类

@Data
public class StripeServiceConfiguration implements ServiceConfiguration {
  private static final TypeOfService serviceType = TypeOfService.STRIPE;
  private Map<String, Object> jsonConfiguration;

  @Override
  public TypeOfService getServiceType() {
    return serviceType;
  }
}

BrainServiceConfiguration 实现类

@Data
public class BrainServiceConfiguration implements ServiceConfiguration {
  private static final TypeOfService serviceType = TypeOfService.BRAIN;
  private Map<String, Object> jsonConfiguration;

  @Override
  public TypeOfService getServiceType() {
    return serviceType;
  }
}

枚举类 TypeOfService

public enum TypeOfService {
  STRIPE("Stripe"),
  BRAIN("Brain");
  
  // 原代码缺失构造方法与Jackson转换注解
}

待反序列化的JSON

{
"serviceConfiguration": {
    "serviceType": "Stripe",
    "jsonConfiguration": {
     .....
     ....
    }}}

报错信息

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot 
construct instance of `com.example.models.payment.ServiceConfiguration` (no Creators, 
like default constructor, exist): abstract types either need to be mapped to concrete 
types, have custom deserializer, or contain additional type information

错误原因

  1. 枚举类配置不完整:原枚举类缺少构造方法、@JsonCreator(字符串转枚举)和@JsonValue(枚举转字符串)注解,导致Jackson无法将JSON中的"Stripe"字符串映射到对应枚举值,进而无法识别子类类型。
  2. 子类类型字段为静态常量:子类的serviceType是静态final字段,Lombok的@Data不会生成静态字段的setter,Jackson无法通过该字段识别类型标识。
  3. 可能的反序列化目标错误:如果直接以ServiceConfiguration作为反序列化目标,未配合外层包装类接收JSON中的serviceConfiguration字段,会导致Jackson无法正确定位类型信息。

修复步骤

1. 完善枚举类配置

补充构造方法与Jackson转换注解,确保字符串与枚举能正确转换:

public enum TypeOfService {
  STRIPE("Stripe"),
  BRAIN("Brain");
  
  private final String value;
  
  TypeOfService(String value) {
    this.value = value;
  }
  
  @JsonCreator
  public static TypeOfService fromValue(String value) {
    for (TypeOfService type : TypeOfService.values()) {
      if (type.value.equals(value)) {
        return type;
      }
    }
    throw new IllegalArgumentException("不支持的服务类型: " + value);
  }
  
  @JsonValue
  public String getValue() {
    return value;
  }
}

2. 调整子类的类型字段

将静态常量改为实例final字段,让Jackson能正确识别类型属性:

@Data
public class StripeServiceConfiguration implements ServiceConfiguration {
  private final TypeOfService serviceType = TypeOfService.STRIPE;
  private Map<String, Object> jsonConfiguration;

  @Override
  public TypeOfService getServiceType() {
    return serviceType;
  }
}

若坚持使用静态字段,需在接口的getServiceType()方法上添加@JsonIgnore,避免Jackson将其作为实例属性处理:

public interface ServiceConfiguration {
  @JsonIgnore
  TypeOfService getServiceType();
}

3. 定义外层包装类

针对JSON的结构,创建包装类接收顶层字段:

@Data
public class ServiceRequest {
  private ServiceConfiguration serviceConfiguration;
}

反序列化时使用该包装类:

ObjectMapper mapper = new ObjectMapper();
ServiceRequest request = mapper.readValue(jsonString, ServiceRequest.class);

4. 版本兼容性检查

确保Jackson的databind、annotations、core三个依赖版本一致,避免版本冲突导致注解失效。

验证

完成上述修改后,重新执行反序列化,Jackson将能正确识别serviceType字段,实例化对应的子类对象,不再抛出抽象类无法实例化的错误。

内容的提问来源于stack exchange,提问作者Amit Pal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 01:51:08