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

如何在不自定义ObjectMapper的情况下序列化只读类并忽略null值

解决Jackson局部序列化忽略Null值的问题

你直接在Controller方法上标注@JsonInclude是无效的,这个注解的作用对象是类、字段或构造方法参数,无法直接作用于Controller方法来控制返回对象的序列化规则。以下是两种符合你需求的声明式解决方案:

方案一:使用Jackson Mixin(适配只读类场景)

这是Jackson原生的声明式方案,无需修改目标类的代码:

  1. 定义一个Mixin抽象类,添加忽略Null值的注解:
@JsonInclude(JsonInclude.Include.NON_NULL)
public abstract class SomeObjectMixin {
}
  1. 在目标接口中,创建局部ObjectMapper并注册Mixin,序列化后返回JSON字符串:
@RestController
public class SomeObjectController {
    @GetMapping(value = "/some-object-with-no-nulls", produces = MediaType.APPLICATION_JSON_VALUE)
    public Mono<String> getSomeObject() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        // 为只读类绑定Mixin规则
        objectMapper.addMixIn(SomeObject.class, SomeObjectMixin.class);
        
        SomeObject obj = new SomeObject(null, "string");
        return Mono.just(objectMapper.writeValueAsString(obj));
    }

    // 只读的SomeObject类(假设无法修改)
    @NoArgsConstructor
    @Getter
    public static class SomeObject {
        private String firstField;
        private String secondField;

        public SomeObject(String firstField, String secondField) {
            this.firstField = firstField;
            this.secondField = secondField;
        }
    }
}

该方案仅对当前接口生效,不会影响其他接口的序列化行为。

方案二:利用ResponseBodyAdvice做局部拦截

如果希望更优雅地复用规则,可以通过Spring的ResponseBodyAdvice实现局部接口的序列化配置:

  1. 创建拦截类,指定仅对目标接口生效:
@ControllerAdvice
public class LocalNonNullSerializationAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 匹配目标方法,可通过方法名、请求路径、自定义注解等方式判断
        return "getSomeObject".equals(returnType.getMethod().getName());
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof Mono) {
            return ((Mono<?>) body).map(this::serializeWithNonNullIgnored);
        }
        return serializeWithNonNullIgnored(body);
    }

    private String serializeWithNonNullIgnored(Object obj) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("序列化失败", e);
        }
    }
}
  1. Controller方法保持原有写法即可:
@GetMapping("/some-object-with-no-nulls")
public Mono<SomeObject> getSomeObject() {
    return Mono.just(new SomeObject(null, "string"));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 01:45:18