SpringBoot实体类JSON字符串映射transient POJO属性返回null问题
问题根因
你的代码存在4个直接导致personDataDetails返回null的问题:
- 注解拼写错误:代码里写的
@JsonIclude是笔误,正确的Jackson序列化控制注解为@JsonInclude,写错的注解不会被Jackson识别生效。 - 字段无实际赋值逻辑:你把JSON反序列化逻辑写在了自定义的
getPersonDataDetails()方法中,但personDataDetails字段本身没有任何赋值操作,@Transient只是JPA提供的、标记字段不参与数据库持久化的注解,框架不会自动调用你写的getter给字段赋值。 - 序列化逻辑冲突:类上标注了Lombok的
@Getter注解会自动生成字段对应的getter,且绝大多数Spring Boot项目默认配置下,Jackson序列化实体时会优先读取字段本身的值,不会触发你手写的带反序列化逻辑的getter,字段初始值就是null,返回结果自然为null。 - 隐藏运行时风险:你在getter中直接调用
objectMapper.readValue方法会抛出JSON解析受检异常,没有做捕获处理的话,一旦逻辑触发会直接导致接口500报错。
修复方案
优先推荐方案1,性能更好,逻辑更清晰:
方案1:实体加载完成后自动解析赋值
利用JPA的@PostLoad生命周期注解,在实体从数据库查询加载完成后,立刻执行JSON解析逻辑给personDataDetails字段赋值,后续序列化直接读取已经赋好值的字段即可,参考实现:
@Entity @Getter // 其余业务注解 public class Person { // 其余业务字段 @Lob @JsonIgnore // 接口返回时忽略原始JSON字符串字段 private String personData; @Transient // 标记该字段不映射数据库列 @JsonInclude(JsonInclude.Include.NON_NULL) // 值为null时不序列化该字段 private PersonData personDataDetails; // 实体从数据库加载完成后自动执行该方法 @PostLoad private void parsePersonData() { if (personData != null && !personData.isEmpty()) { try { // 推荐直接注入Spring容器中已配置好的单例ObjectMapper,不要每次new对象浪费性能 ObjectMapper objectMapper = SpringContextUtil.getBean(ObjectMapper.class); this.personDataDetails = objectMapper.readValue(personData, PersonData.class); } catch (JsonProcessingException e) { // 自行补充异常日志打印逻辑,不要把异常直接抛到上层 e.printStackTrace(); } } } // 不需要额外手写getPersonDataDetails方法,Lombok生成的getter会直接返回解析好的字段值 }
方案2:去掉冗余字段,直接通过getter输出序列化结果
如果不想加生命周期回调逻辑,可以删掉personDataDetails的字段定义,只保留带解析逻辑的getter,通过注解告诉Jackson直接读取getter返回值作为序列化结果,参考实现:
@Entity @Getter // 其余业务注解 public class Person { // 其余业务字段 @Lob @JsonIgnore private String personData; // 删掉personDataDetails字段定义,只保留getter @JsonProperty("personDataDetails") // 指定序列化后的字段名 @JsonInclude(JsonInclude.Include.NON_NULL) public PersonData getPersonDataDetails(){ if (personData == null || personData.isEmpty()) { return null; } try { ObjectMapper objectMapper = SpringContextUtil.getBean(ObjectMapper.class); return objectMapper.readValue(personData, PersonData.class); } catch (JsonProcessingException e) { e.printStackTrace(); return null; } } }
注意:方案2每次序列化实体都会重新执行一次JSON解析,如果同一个实体被多次序列化会重复做无用计算,性能远低于方案1,非特殊场景不推荐使用。
内容的提问来源于stack exchange,提问作者newcoder
相关产品推荐
相关产品推荐

