You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 00:45:54