Java无需Jackson ObjectMapper调用子类方法的合适设计模式是什么?
现有实现合理性评估
当前先序列化再反序列化的实现并非完全无法运行,但严重不符合Java最佳实践,存在明确的设计缺陷:
- 性能冗余损耗:两次JSON序列化/反序列化的CPU、内存开销完全不必要,数据量较大时性能下降会非常明显
- 类型安全缺失:所有转换错误只会在运行时暴露,编译期无法提前校验
- 隐性故障风险:如果类字段发生增删修改、或者存在Jackson不支持序列化的类型,会直接出现数据丢失或运行异常
- 可读性差:多绕了一层序列化逻辑,后续维护人员很难快速理解转换意图
不依赖ObjectMapper的实现方案
前置优化:先修正类结构的字段隐藏问题
子类ExtendedClass重复定义了父类AbstractClass已经存在的first、second字段,会导致字段隐藏问题,先清理重复字段,同时可以给父类加上泛型避免后续强转:
// 泛型改造后的抽象父类 @Getter @NoArgsConstructor @AllArgsConstructor @SuperBuilder(toBuilder=true) @Accessors(chain = true) public abstract class AbstractClass<T> { private String first; private T second; }
// 清理重复字段后的子类 @Setter @Getter @EqualsAndHashCode(callSuper = true) @SuperBuilder(toBuilder=true) @AllArgsConstructor @NoArgsConstructor @Accessors(chain = true) public class ExtendedClass extends AbstractClass<ExtendedClass.Second> { public static final String FIRST_TYPE= "EXTENDED"; @Getter public static class Second { private String value; } }
方案1:保留Jackson做初始JSON解析,仅替换冗余二次转换逻辑(推荐)
用工厂模式封装不同类型的转换逻辑,完全去掉二次序列化反序列化的步骤:
public class PropConverter { // 注册所有支持的类型和对应转换逻辑,后续新增类型只需要加注册项即可 private static final Map<String, Function<AbstractClass<?>, SomeProps>> CONVERTER_MAP = Map.of( ExtendedClass.FIRST_TYPE, PropConverter::convertExtended ); @SneakyThrows public SomeProps mapProps(String value) { try { Values values = objectMapper.readValue(value, Values.class); AbstractClass<?> valueProp = values.getProp(); if (valueProp == null || valueProp.getFirst() == null) { return null; } Function<AbstractClass<?>, SomeProps> converter = CONVERTER_MAP.get(valueProp.getFirst()); return converter != null ? converter.apply(valueProp) : null; } catch (JsonProcessingException e) { log.error("JSON处理异常", e); return null; } } // 单独封装Extended类型的转换逻辑,类型安全 private static SomeProps convertExtended(AbstractClass<?> raw) { if (!(raw.getSecond() instanceof ExtendedClass.Second second)) { throw new IllegalArgumentException("second字段类型不匹配"); } // 直接构造ExtendedClass对象,无冗余操作 ExtendedClass extended = ExtendedClass.builder() .first(raw.getFirst()) .second(second) .build(); // 调用原有逻辑转换为SomeProps return map(extended); } // 你原有map方法保留即可 private static SomeProps map(ExtendedClass extended) { // 原有转换逻辑 } }
方案2:完全移除Jackson依赖,用JDK原生API实现(JDK11及以上支持)
如果需要完全去掉Jackson依赖,可以用JDK自带的java.json API实现JSON解析:
import javax.json.Json; import javax.json.JsonObject; import java.io.StringReader; public class PropConverter { public SomeProps mapProps(String value) { try (var reader = Json.createReader(new StringReader(value))) { JsonObject root = reader.readObject(); JsonObject propObj = root.getJsonObject("prop"); String type = propObj.getString("first"); if (ExtendedClass.FIRST_TYPE.equals(type)) { JsonObject secondObj = propObj.getJsonObject("second"); // 手动构造Second对象 ExtendedClass.Second second = new ExtendedClass.Second(); second.setValue(secondObj.getString("value")); // 构造ExtendedClass对象 ExtendedClass extended = new ExtendedClass(); extended.setFirst(type); extended.setSecond(second); return map(extended); } return null; } catch (Exception e) { log.error("JSON解析异常", e); return null; } } private static SomeProps map(ExtendedClass extended) { // 原有转换逻辑 } }
内容的提问来源于stack exchange,提问作者xeLL
相关产品推荐
相关产品推荐

