启用自定义getter触发HttpMessageNotWritableException异常求助
问题解决:自定义Getter导致JSON序列化异常
问题现象
启用getState()自定义方法时,触发org.springframework.http.converter.HttpMessageNotWritableException异常;注释该方法后异常消失。需求是通过此Getter从持久化字段stateId计算生成瞬态值state(stateId的完整描述)。
异常日志:
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: 1; nested exception is com.fasterxml.jackson.databind.JsonMappingException: 1 (through reference chain: com.example.model.Employee["state"])]
实体类原代码:
@Data @AllArgsConstructor @NoArgsConstructor @Builder @Entity public class Employee implements Serializable { @Id @GeneratedValue(generator = UUIDGenerator.UUID_GEN_STRATEGY ) //strategy = GenerationType.IDENTITY UUID id ; @Column String name; @Column String telephone; @Column String address; @Enumerated @JsonIgnore @Column(name="state", nullable = false) State stateId; @Transient List<String> state; public Employee(BaseEmployeeRequest employee) { stateId = State.ADDED; this.name = employee.getName(); this.address = employee.getAddress(); this.telephone = employee.getTelephone(); } public void setState(List<String> state) { this.state = state; } public List<String> getState(){ List<String> state = new ArrayList<String>(); if(stateId !=null) { String[] states = stateId.getId().split("_"); if(states[1] ==null || states[1].length()==0){ state.add(states[0]); state.add(EventFullName.SECURITY.get(states[1])); state.add(EventFullName.SECURITY.get(states[2])); } return state; } return Collections.EMPTY_LIST; } }
异常原因
核心问题是getState()方法中的数组越界异常:
- 当
stateId.getId()分割后的数组states长度小于2或3时,直接访问states[1]、states[2]会抛出ArrayIndexOutOfBoundsException - 该异常被Jackson捕获后转换为
JsonMappingException,最终引发HttpMessageNotWritableException - 同时判断逻辑存在错误:
if(states[1] ==null || states[1].length()==0)本身就存在访问风险——如果states长度不足2,访问states[1]直接报错
修复方案
1. 修复数组越界与逻辑错误
调整getState()方法,先判断数组长度,再安全访问元素:
public List<String> getState(){ List<String> state = new ArrayList<>(); if(stateId == null) { return Collections.emptyList(); } String[] states = stateId.getId().split("_"); // 优先添加第一个元素(确保存在) if(states.length > 0) { state.add(states[0]); } // 数组长度足够且第二个元素非空时,添加后续内容 if(states.length > 1 && states[1].length() > 0) { state.add(EventFullName.SECURITY.get(states[1])); // 数组长度足够时再添加第三个元素 if(states.length > 2) { state.add(EventFullName.SECURITY.get(states[2])); } } return state; }
2. 避免Lombok与自定义Getter冲突
因为使用了@Data注解,它会自动生成getState()方法,虽然编译时会优先使用自定义方法,但可以通过以下方式明确声明:
- 在自定义
getState()上添加@JsonGetter("state"),明确指定该方法为JSON序列化时的Getter - 或者移除
@Data,改用@Getter、@Setter注解单独标注需要自动生成方法的字段,避免和自定义方法冲突
额外注意事项
- 确保
EventFullName.SECURITY.get()方法不会返回null,否则可能导致JSON序列化时出现空值问题 - 测试不同格式的
stateId.getId()值,确保所有场景下数组访问都安全
内容的提问来源于stack exchange,提问作者Shima Mahmoud
相关产品推荐
相关产品推荐

