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

Jackson反序列化抽象类报错:无法构造AbstractJsonResult实例

解决Jackson反序列化抽象Result类的问题

你的问题核心是:只给顶层的AbstractJson配置了子类类型识别,但嵌套的AbstractJsonResult作为抽象类,Jackson没有足够信息确定要实例化哪个具体子类,所以抛出了无法构造抽象类实例的错误。下面给两种适配你需求的解决方案:


方案一:给AbstractJsonResult绑定顶层request_name的类型信息

利用@JsonTypeInfo的EXTERNAL_PROPERTY特性,让Jackson通过顶层的request_name属性来确定result对应的具体子类。

代码示例

  1. 定义抽象Result类及子类
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
    property = "request_name" // 关联顶层的request_name字段
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = UserResult.class, name = "get_user"),
    @JsonSubTypes.Type(value = OrderResult.class, name = "get_order")
})
public abstract class AbstractJsonResult {
    // 所有Result共享的属性可以定义在这里
}

// 具体Result子类1
public class UserResult extends AbstractJsonResult {
    private String username;
    private Integer age;

    // 必须提供无参构造器(Jackson默认需要)
    public UserResult() {}

    // getter、setter方法
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
}

// 具体Result子类2
public class OrderResult extends AbstractJsonResult {
    private String orderId;
    private Double amount;

    public OrderResult() {}

    // getter、setter方法
    public String getOrderId() { return orderId; }
    public void setOrderId(String orderId) { this.orderId = orderId; }
    public Double getAmount() { return amount; }
    public void setAmount(Double amount) { this.amount = amount; }
}
  1. 定义顶层抽象类及子类
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "request_name"
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = UserJson.class, name = "get_user"),
    @JsonSubTypes.Type(value = OrderJson.class, name = "get_order")
})
public abstract class AbstractJson {
    private Integer error;
    private AbstractJsonResult result;

    public AbstractJson() {}

    // getter、setter方法
    public Integer getError() { return error; }
    public void setError(Integer error) { this.error = error; }
    public AbstractJsonResult getResult() { return result; }
    public void setResult(AbstractJsonResult result) { this.result = result; }
}

// 顶层子类1
public class UserJson extends AbstractJson {}

// 顶层子类2
public class OrderJson extends AbstractJson {}
  1. 反序列化测试
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestDeserialization {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        
        // 测试get_user类型的JSON
        String userJson = "{\"error\":0,\"request_name\":\"get_user\",\"result\":{\"username\":\"jack\",\"age\":25}}";
        AbstractJson userObj = mapper.readValue(userJson, AbstractJson.class);
        System.out.println(((UserResult)userObj.getResult()).getUsername()); // 输出jack
        
        // 测试get_order类型的JSON
        String orderJson = "{\"error\":0,\"request_name\":\"get_order\",\"result\":{\"orderId\":\"ORD123\",\"amount\":99.9}}";
        AbstractJson orderObj = mapper.readValue(orderJson, AbstractJson.class);
        System.out.println(((OrderResult)orderObj.getResult()).getOrderId()); // 输出ORD123
    }
}

方案二:直接在顶层子类中绑定具体Result类型

如果Result之间没有共享属性,或者不想给抽象Result类配置类型信息,可以直接在每个顶层子类里定义具体的Result类型,避免抽象类的反序列化问题。

代码示例

  1. 定义具体Result类
public class UserResult {
    private String username;
    private Integer age;

    public UserResult() {}

    // getter、setter方法
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
}

public class OrderResult {
    private String orderId;
    private Double amount;

    public OrderResult() {}

    // getter、setter方法
    public String getOrderId() { return orderId; }
    public void setOrderId(String orderId) { this.orderId = orderId; }
    public Double getAmount() { return amount; }
    public void setAmount(Double amount) { this.amount = amount; }
}
  1. 定义顶层抽象类及子类
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "request_name"
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = UserJson.class, name = "get_user"),
    @JsonSubTypes.Type(value = OrderJson.class, name = "get_order")
})
public abstract class AbstractJson {
    private Integer error;

    public AbstractJson() {}

    public Integer getError() { return error; }
    public void setError(Integer error) { this.error = error; }
}

public class UserJson extends AbstractJson {
    private UserResult result;

    public UserJson() {}

    public UserResult getResult() { return result; }
    public void setResult(UserResult result) { this.result = result; }
}

public class OrderJson extends AbstractJson {
    private OrderResult result;

    public OrderJson() {}

    public OrderResult getResult() { return result; }
    public void setResult(OrderResult result) { this.result = result; }
}
  1. 反序列化测试
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestDeserialization {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        
        String userJson = "{\"error\":0,\"request_name\":\"get_user\",\"result\":{\"username\":\"jack\",\"age\":25}}";
        UserJson userObj = mapper.readValue(userJson, UserJson.class);
        System.out.println(userObj.getResult().getUsername()); // 输出jack
        
        String orderJson = "{\"error\":0,\"request_name\":\"get_order\",\"result\":{\"orderId\":\"ORD123\",\"amount\":99.9}}";
        OrderJson orderObj = mapper.readValue(orderJson, OrderJson.class);
        System.out.println(orderObj.getResult().getOrderId()); // 输出ORD123
    }
}

关键注意点

  • 所有被Jackson反序列化的类必须提供无参构造器,否则Jackson无法实例化对象。
  • 方案一适合Result有共享属性的场景,能复用代码;方案二更简洁,适合Result结构差异较大的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 07:28:20