Jackson反序列化抽象类报错:无法构造AbstractJsonResult实例
解决Jackson反序列化抽象Result类的问题
你的问题核心是:只给顶层的AbstractJson配置了子类类型识别,但嵌套的AbstractJsonResult作为抽象类,Jackson没有足够信息确定要实例化哪个具体子类,所以抛出了无法构造抽象类实例的错误。下面给两种适配你需求的解决方案:
方案一:给AbstractJsonResult绑定顶层request_name的类型信息
利用@JsonTypeInfo的EXTERNAL_PROPERTY特性,让Jackson通过顶层的request_name属性来确定result对应的具体子类。
代码示例
- 定义抽象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; } }
- 定义顶层抽象类及子类
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 {}
- 反序列化测试
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类型,避免抽象类的反序列化问题。
代码示例
- 定义具体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; } }
- 定义顶层抽象类及子类
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; } }
- 反序列化测试
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
相关产品推荐
相关产品推荐

