如何通过继承消除API响应类重复代码并兼容Jackson反序列化?
基于泛型+继承消除API响应类重复代码的最优方案
针对你描述的两个API响应类仅内部Data字段类型不同的场景,用泛型抽象父类+具体子类的方案是最简洁且适配Jackson反序列化要求的实现方式,具体步骤如下:
1. 抽象公共结构为泛型父类
将两个类的重复部分(响应码、消息、Data容器)抽离到一个泛型父类中,用泛型<T>表示不同的Data类型:
import com.fasterxml.jackson.annotation.JsonProperty; // 抽象父类,定义公共响应结构 public abstract class BaseApiResponse<T> { @JsonProperty("code") private int responseCode; @JsonProperty("message") private String responseMessage; @JsonProperty("data") private T responseData; // 公共的Getter/Setter,无需重复编写 public int getResponseCode() { return responseCode; } public void setResponseCode(int responseCode) { this.responseCode = responseCode; } public String getResponseMessage() { return responseMessage; } public void setResponseMessage(String responseMessage) { this.responseMessage = responseMessage; } public T getResponseData() { return responseData; } public void setResponseData(T responseData) { this.responseData = responseData; } }
2. 定义具体的Data实体类
分别创建两个类对应的Data类型,仅保留各自独有的字段:
import java.math.BigDecimal; // ClassA对应的Data实体 public class UserData { @JsonProperty("user_id") private Long userId; @JsonProperty("user_name") private String userName; // 该类的Getter/Setter public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } } // ClassB对应的Data实体 public class OrderData { @JsonProperty("order_id") private String orderId; @JsonProperty("order_amount") private BigDecimal orderAmount; // 该类的Getter/Setter public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public BigDecimal getOrderAmount() { return orderAmount; } public void setOrderAmount(BigDecimal orderAmount) { this.orderAmount = orderAmount; } }
3. 创建子类继承泛型父类
两个原响应类只需继承父类并指定泛型类型,无需编写任何重复代码:
// 原ClassA,指定泛型为UserData public class ClassA extends BaseApiResponse<UserData> { // 空实现,所有公共属性和方法直接继承自父类 } // 原ClassB,指定泛型为OrderData public class ClassB extends BaseApiResponse<OrderData> { // 空实现,所有公共属性和方法直接继承自父类 }
4. Jackson反序列化用法
由于子类已经明确指定了泛型类型,直接使用子类的Class对象即可完成反序列化,无需额外复杂配置:
import com.fasterxml.jackson.databind.ObjectMapper; ObjectMapper objectMapper = new ObjectMapper(); // 反序列化ClassA String classAJson = "{\"code\":200,\"message\":\"请求成功\",\"data\":{\"user_id\":1001,\"user_name\":\"张三\"}}"; ClassA classA = objectMapper.readValue(classAJson, ClassA.class); // 反序列化ClassB String classBJson = "{\"code\":200,\"message\":\"请求成功\",\"data\":{\"order_id\":\"ORD20240501\",\"order_amount\":99.9}}"; ClassB classB = objectMapper.readValue(classBJson, ClassB.class);
关键注意事项
- 父类建议设为抽象类,避免直接实例化,更符合语义。
- 所有与JSON字段映射的注解(如
@JsonProperty)统一放在父类的公共字段上,子类无需重复配置。 - 如果后续某个响应类需要新增独有的字段,直接在对应子类中添加即可,不会破坏公共结构。
内容的提问来源于stack exchange,提问作者wuttke
相关产品推荐
相关产品推荐

