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

Spring Boot中如何处理空RequestBody?无法修改Swagger生成模型类

解决方案:Spring Boot中拦截空JSON请求体(模型类不可修改)

我之前帮同事处理过完全一样的场景——Swagger生成的模型类碰不得,但又要避免空JSON被转换成全null的实例。下面几个方案都能解决问题,按优雅度和适用场景排序:

1. 自定义RequestBodyAdvice(全局拦截,推荐)

Spring提供的RequestBodyAdvice可以在请求体被转换成Java对象的前后插入自定义逻辑,完美适配这种不能修改模型类的场景,一次配置全局生效。

实现步骤:

  • 创建类实现RequestBodyAdvice,加@ControllerAdvice让Spring扫描到
  • 在supports方法里指定要拦截的目标模型类
  • 在afterBodyRead方法里检查转换后的对象是否所有字段都为null,是的话直接抛异常

代码示例:

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.lang.reflect.Field;
import java.lang.reflect.Type;

@ControllerAdvice
public class EmptyRequestBodyCheckAdvice implements RequestBodyAdvice {

    // 指定要拦截的模型类,替换成你的实际类名
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return targetType.getTypeName().equals(YourRequestModel.class.getName());
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return inputMessage;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        if (isAllFieldsNull(body)) {
            throw new RuntimeException("All fields are empty.");
        }
        return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 处理完全没有请求体的情况(不是{},而是空内容)
        throw new RuntimeException("Request body cannot be empty.");
    }

    // 反射遍历字段,判断是否全为null
    private boolean isAllFieldsNull(Object obj) {
        for (Field field : obj.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            try {
                if (field.get(obj) != null) {
                    return false;
                }
            } catch (IllegalAccessException e) {
                // 反射异常可以打日志或者做其他处理
                e.printStackTrace();
            }
        }
        return true;
    }
}

2. Controller层手动检查(适合单个端点)

如果只有一个端点用到这个模型类,直接在Controller方法里加检查逻辑最直接,不用写全局组件。可以封装一个工具类复用检查逻辑:

// 封装检查工具类
public class ObjectCheckUtils {
    public static boolean isAllFieldsNull(Object obj) {
        if (obj == null) return true;
        for (Field field : obj.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            try {
                if (field.get(obj) != null) {
                    return false;
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return true;
    }
}

// Controller中的用法
@PostMapping("/your-api-endpoint")
public ResponseEntity<?> handleRequest(@RequestBody YourRequestModel requestObj) {
    if (ObjectCheckUtils.isAllFieldsNull(requestObj)) {
        throw new RuntimeException("All fields are empty.");
    }
    // 后续业务逻辑处理
    return ResponseEntity.ok("Processed successfully");
}

3. Jackson Mixin + 自定义反序列化器(进阶方案)

如果想从序列化源头拦截空JSON,可以用Jackson的Mixin功能——不用修改原模型类,就能给它绑定自定义反序列化逻辑:

步骤:

  • 创建一个和模型类字段匹配的Mixin接口
  • 写自定义反序列化器,检查JSON是否为空
  • 在Spring Boot中注册Mixin和反序列化器

代码示例:

// Mixin接口,和你的模型类结构保持一致
public interface YourRequestModelMixin {
}

// 自定义反序列化器
public class EmptyCheckDeserializer extends StdDeserializer<YourRequestModel> {
    protected EmptyCheckDeserializer() {
        super(YourRequestModel.class);
    }

    @Override
    public YourRequestModel deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        // 检查JSON节点是否没有任何非空字段
        if (node.isEmpty()) {
            throw new RuntimeException("All fields are empty.");
        }
        // 用默认逻辑转换对象
        ObjectMapper mapper = (ObjectMapper) p.getCodec();
        return mapper.treeToValue(node, YourRequestModel.class);
    }
}

// 注册到Spring容器
@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.addMixIn(YourRequestModel.class, YourRequestModelMixin.class);
        mapper.registerModule(new SimpleModule()
                .addDeserializer(YourRequestModel.class, new EmptyCheckDeserializer()));
        return mapper;
    }
}

注意事项:

  • 如果模型类里有基本数据类型(比如int、boolean),空JSON会把它们转换成默认值(0、false),这时候需要调整isAllFieldsNull的逻辑,判断这些默认值是否属于“空”的范畴
  • 全局拦截方案适合多个端点共用同一模型类的场景,能减少重复代码
  • 要是需要更友好的前端提示,可以自定义业务异常,再用@ExceptionHandler统一处理返回格式

内容的提问来源于stack exchange,提问作者mi.mo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:43:12