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

Spring MVC中如何将@RequestBody对象的空字符串属性转为null?

如何在Spring @RequestBody中仅针对特定方法将空字符串转为null?

针对你的需求(仅在save方法中将所有空/空白字符串(包括嵌套属性)转为null),可以采用以下两种方案:

方案一:使用@RequestBodyAdvice(推荐,无需手动处理请求体)

通过@RequestBodyAdvice可以在@RequestBody反序列化完成后对目标对象进行修改,并且能精准限定作用的方法和参数类型。

1. 实现RequestBodyAdvice

@ControllerAdvice
public class EmptyStringToNullAdvice implements RequestBodyAdvice {

    @Override
    public boolean supports(MethodParameter methodParam, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 仅作用于save方法,且参数类型为Car
        return "save".equals(methodParam.getMethod().getName()) 
                && Car.class.getName().equals(targetType.getTypeName());
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMsg, MethodParameter param, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        return inputMsg;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMsg, MethodParameter param, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 递归遍历对象,将空/空白字符串转为null
        convertEmptyStringsToNull(body);
        return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMsg, MethodParameter param, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

    private void convertEmptyStringsToNull(Object obj) {
        if (obj == null) return;

        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(obj);
                if (value instanceof String) {
                    String strValue = (String) value;
                    if (strValue.trim().isEmpty()) {
                        field.set(obj, null);
                    }
                } else if (value != null && !field.getType().isPrimitive() && !Collection.class.isAssignableFrom(field.getType())) {
                    // 递归处理嵌套对象
                    convertEmptyStringsToNull(value);
                }
            } catch (IllegalAccessException e) {
                // 可根据实际需求添加日志或异常处理
                e.printStackTrace();
            }
        }
    }
}

2. 原控制器方法无需修改

你的save方法保持原样即可:

@PutMapping
public void save(@RequestBody Car car) {
    // 此时car中的空/空白字符串已转为null
}

方案二:自定义Jackson反序列化器+局部ObjectMapper

如果希望直接通过Jackson的序列化机制处理,可以自定义字符串反序列化器,然后为save方法单独配置ObjectMapper。

1. 自定义字符串反序列化器

public class EmptyStringToNullDeserializer extends StdDeserializer<String> {

    public EmptyStringToNullDeserializer() {
        super(String.class);
    }

    @Override
    public String deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        String value = parser.getText();
        return (value == null || value.trim().isEmpty()) ? null : value;
    }
}

2. 注册自定义模块

public class EmptyStringModule extends SimpleModule {
    public EmptyStringModule() {
        addDeserializer(String.class, new EmptyStringToNullDeserializer());
    }
}

3. 在控制器中使用自定义ObjectMapper

手动读取请求体并反序列化(注意这种方式需要放弃@RequestBody注解):

@RestController
public class CarController {

    private final ObjectMapper defaultMapper;
    private final ObjectMapper customMapper;

    // 注入默认ObjectMapper,复制后添加自定义模块
    public CarController(ObjectMapper defaultMapper) {
        this.defaultMapper = defaultMapper;
        this.customMapper = defaultMapper.copy();
        this.customMapper.registerModule(new EmptyStringModule());
    }

    @PutMapping
    public void save(HttpServletRequest request) throws IOException {
        // 读取请求体
        String requestBody = request.getReader().lines().collect(Collectors.joining());
        // 使用自定义ObjectMapper反序列化
        Car car = customMapper.readValue(requestBody, Car.class);
        // 后续业务逻辑
    }
}

方案对比

  • 方案一:无需修改原控制器方法,通过切面式处理实现,代码侵入性低,更符合Spring的开发习惯。
  • 方案二:直接基于Jackson机制处理,适合需要更精细控制序列化逻辑的场景,但需要手动处理请求体。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:24:51