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

Spring Boot REST API异常捕获最佳实践:处理JSON解析异常

这个问题在Spring Boot开发中太常见了!我来分享几个生产环境里验证过的最佳实践,帮你优雅处理这类异常:

1. 全局统一异常处理(核心方案)

Spring提供了@RestControllerAdvice和@ExceptionHandler注解,可以全局捕获并处理这类JSON解析异常,不用在每个Controller里重复写异常处理逻辑。

你可以创建一个全局异常处理器,专门处理HttpMessageNotReadableException(Spring会把底层的JsonParseException包装成这个异常),返回友好的错误响应给前端,而不是暴露底层的异常细节:

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 处理JSON解析格式错误、参数无法绑定的异常
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<ErrorResponse> handleJsonParseError(HttpMessageNotReadableException ex) {
        Throwable rootCause = ex.getRootCause();
        String errorMsg;
        if (rootCause instanceof JsonParseException) {
            errorMsg = "请求JSON格式错误:" + rootCause.getMessage().split("\\(")[0]; // 简化错误信息,避免太技术化
        } else {
            errorMsg = "请求参数格式不正确,请检查输入内容";
        }
        ErrorResponse response = new ErrorResponse(HttpStatus.BAD_REQUEST.value(), errorMsg);
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }

    // 顺便处理参数校验异常(比如字段为空、长度不符合要求)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationError(MethodArgumentNotValidException ex) {
        StringBuilder errorMsg = new StringBuilder();
        ex.getBindingResult().getAllErrors().forEach(error -> {
            errorMsg.append(error.getDefaultMessage()).append("; ");
        });
        ErrorResponse response = new ErrorResponse(HttpStatus.BAD_REQUEST.value(), errorMsg.toString());
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }

    // 自定义标准化错误响应类
    static class ErrorResponse {
        private int status;
        private String message;

        public ErrorResponse(int status, String message) {
            this.status = status;
            this.message = message;
        }

        // Getter和Setter(或者用Lombok的@Data简化)
        public int getStatus() { return status; }
        public void setStatus(int status) { this.status = status; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
    }
}

2. 开启请求参数校验,提前拦截非法数据

光处理解析异常还不够,我们可以提前校验请求参数的合法性。给@RequestBody的参数加上@Valid注解,同时在Student类的字段上添加校验注解,比如@NotBlank、@Size等:

第一步:给Student类添加校验注解

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

// 如果是Spring Boot 2.x,用javax.validation.constraints.*
@JsonIgnoreProperties(ignoreUnknown = true) // 后面会讲这个注解的作用
public class Student {
    @NotBlank(message = "用户名不能为空")
    private String username;

    @NotBlank(message = "密码不能为空")
    @Size(min = 6, message = "密码长度不能少于6位")
    private String password;

    // 其他字段、Getter和Setter
}

第二步:在Controller方法里启用校验

@RequestMapping(method = RequestMethod.POST, value = "/student")
public ResponseEntity<Void> addStudent(@Valid @RequestBody Student student) {
    student.setPassword(bCryptPasswordEncoder.encode(student.getPassword()));
    studentService.addStudent(student);
    return ResponseEntity.status(HttpStatus.CREATED).build();
}

这样如果前端传的JSON格式正确,但字段不符合业务要求(比如密码太短),会抛出MethodArgumentNotValidException,上面的全局处理器会捕获并返回明确的错误提示。

3. 配置Jackson容错,提高接口兼容性

有时候前端可能会传一些Student类里没有的字段,默认情况下Jackson会抛出异常。我们可以配置Jackson忽略未知字段,或者允许一些容错行为:

方式一:通过配置文件(application.yml)全局配置

spring:
  jackson:
    deserialization:
      fail-on-unknown-properties: false # 忽略未知字段
      accept-empty-string-as-null-object: true # 允许空字符串转为null

方式二:在实体类上单独配置

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Student {
    // 字段...
}

这样即使前端多传了字段,接口也不会报错,只会忽略这些无关字段,提高接口的兼容性。

4. 返回标准化的错误响应

不管是解析异常还是参数校验异常,都返回统一格式的错误响应(比如上面的ErrorResponse),这样前端可以统一处理错误逻辑,不用适配不同的错误格式。


内容的提问来源于stack exchange,提问作者babastyle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:54:15