Spring Boot 接口 JSON 序列化优化:忽略 Null 值的九种解决方案详解

news2025/3/5 9:27:35

一、针对特定接口null的处理:

方法一:使用 @JsonInclude 注解

1.1 类级别:在接口返回的 ‌DTO 类或字段‌ 上添加 @JsonInclude 注解,强制忽略 null 值:

类级别:所有字段为 null 时不返回

@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyResponseDTO {
    private String field1;
    

1.2 字段级别:在具体字段上,仅该字段为 null 时不返回

// 字段级别:仅该字段为 null 时不返回
@JsonInclude(JsonInclude.Include.NON_NULL)
private String field2;

1.3 方法级别: 在方法级别使用 @JsonInclude

如果不想在 DTO 类上全局标注 @JsonInclude,可以直接在 Controller 方法的返回类型上通过 @JsonSerialize 注解临时指定序列化行为。

@GetMapping("/user")
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) // 旧版 Jackson 注解
public MyResponse getUser() {
    MyResponse response = new MyResponse();
    response.setName("Alice"); // age 为 null,不返回
    return response;
}

方法二:动态构建响应对象

在 Controller 方法中手动过滤 null 值,使用 Map 或 JSONObject 动态构建响应体:

@GetMapping("/api")
public Map<String, Object> getData() {
    MyResponseDTO dto = service.getData();
    Map<String, Object> result = new HashMap<>();
    if (dto.getField1() != null) {
        result.put("field1", dto.getField1());
    }
    return result;
}

适用于简单场景,但需手动维护字段映射‌。

方法三:自定义序列化逻辑(针对复杂场景)

通过继承 JsonSerializer 实现特定字段的 null 处理逻辑,并在 DTO 中指定序列化器:

public class NullSerializer extends JsonSerializer<Object> {
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) {
        // 忽略 null 字段
        if (value == null) {
            return;
        }
        gen.writeObject(value);
    }
}

// 在 DTO 字段上指定序列化器
public class MyResponseDTO {
    @JsonSerialize(using = NullSerializer.class)
    private String field1;
}

适用于需要精细化控制序列化逻辑的场景‌。

方法四:自定义 ObjectMapper 并局部使用

通过注入 ObjectMapper 实例,在特定接口中手动序列化数据,跳过 null 值。

@Autowired
private ObjectMapper objectMapper;

@GetMapping("/user")
public String getUser(HttpServletResponse response) throws JsonProcessingException {
    MyResponse data = new MyResponse();
    data.setName("Alice"); // age 为 null

    // 临时配置 ObjectMapper 忽略 null
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    String json = objectMapper.writeValueAsString(data);
    
    // 恢复全局配置(可选)
    objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
    
    response.setContentType(MediaType.APPLICATION_JSON_VALUE);
    return json;
}

注意:此方法需手动处理响应,适用于需要完全控制序列化逻辑的场景,但需谨慎管理 ObjectMapper 的线程安全性。

方法五:使用 ResponseBodyAdvice 全局拦截并处理

通过实现 ResponseBodyAdvice 接口,对特定接口或全局返回值进行统一处理。

  1. 定义切面类

    @RestControllerAdvice
    public class NullIgnoreAdvice implements ResponseBodyAdvice<Object> {
    
        @Override
        public boolean supports(MethodParameter returnType, Class converterType) {
            // 仅处理特定接口(根据注解、包路径等条件判断)
            return returnType.getExecutable().getName().equals("getUser");
        }
    
        @Override
        public Object beforeBodyWrite(Object body, MethodParameter returnType, 
                                     MediaType mediaType, Class selectedConverterType,
                                     ServerHttpRequest request, ServerHttpResponse response) {
            if (body instanceof MyResponse) {
                // 手动移除 null 值(需根据数据结构处理)
                ((MyResponse) body).setAge(null); // 示例
            }
            return body;
        }
    }
    
  2. 结合 ObjectMapper 动态过滤
    beforeBodyWrite 中重新序列化数据:

    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    return mapper.convertValue(body, returnType.getParameterType());
    

二、针对所有接口null 的处理:

2.1 :全局配置(影响所有接口)

若需所有接口忽略null值,可在application.properties中配置:

spring.jackson.default-property-inclusion=non_null

2.2 Springboot 整合 fastjson:

在springboot 启动类中定义该方法即可

  @Bean
  public HttpMessageConverters fastJsonHttpMessageConverters() {
    FastJsonHttpMessageConverter4 fastConverter = new FastJsonHttpMessageConverter4();
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, SerializerFeature.IgnoreNonFieldGetter,
        SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
    fastConverter.setFastJsonConfig(fastJsonConfig);
    List supportedMediaTypes = new ArrayList();
    supportedMediaTypes.add(new MediaType("text", "json", Charset.forName("utf8")));
    supportedMediaTypes.add(new MediaType("application", "json", Charset.forName("utf8")));
    fastConverter.setSupportedMediaTypes(supportedMediaTypes);
    HttpMessageConverter<?> converter = fastConverter;
    return new HttpMessageConverters(converter);
  }

2.3 Springboot 整合 jackson:

@Configuration
public class JacksonConfig {
  @Bean
  @Primary
  @ConditionalOnMissingBean(ObjectMapper.class)
  public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();
    objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
      @Override
      public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString("");
      }
    });
    return objectMapper;
  }
}

三、总结:

  1. 针对新项目,推荐使用全局序列化处理,统一返回值。
  2. 针对老项目,推荐使用特定接口的处理,避免影响了其他接口的稳定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2309940.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解码未来!安徽艾德未来智能科技有限公司荣获“GAS消费电子科创奖-产品创新奖”!

在2025年“GAS消费电子科创奖”评选中&#xff0c;安徽艾德未来智能科技有限公司提交的“讯飞AI会议耳机iFLYBUDS Pro 2”&#xff0c;在技术创新性、设计创新性、工艺创新性、智能化创新性及原创性五大维度均获得评委的高度认可&#xff0c;荣获“产品创新奖”。 这一殊荣不仅…

力扣hot100刷题——栈

文章目录 69.有效的括号题目描述思路&#xff1a;栈code 70.最小栈题目描述思路&#xff1a;双栈法code优化&#xff1a;单栈法code 71.字符串解码题目描述思路&#xff1a;栈code 73.每日温度题目描述思路&#xff1a;单调栈code 74.柱状图中最大的矩形题目描述思路&#xff1…

TMS320F28P550SJ9学习笔记2:Sysconfig 配置与点亮LED

今日学习使用Sysconfig 对引脚进行配置&#xff0c;并点亮开发板上的LED4 与LED5 我的单片机开发板平台是 LAUNCHXL_F28P55x 我是在上文描述的驱动库C2000ware官方例程example的工程基础之上进行添加功能的 该例程路径如下&#xff1a;D:\C2000Ware_5_04_00_00\driverlib\f28p…

健康养生:开启活力人生的钥匙

在快节奏的现代生活中&#xff0c;健康养生已成为我们追求美好生活的关键。它不仅关乎身体的强健&#xff0c;更与心灵的宁静息息相关。 合理饮食是健康养生的基石。多吃蔬菜、水果&#xff0c;它们富含维生素与矿物质&#xff0c;为身体提供充足养分。全谷物食品也是不错的选…

HTTP 与 HTTPS 协议:从基础到安全强化

引言 互联网的消息是如何传递的&#xff1f; 是在路由器上不断进行跳转 IP的目的是在寻址 HTTP 协议&#xff1a;互联网的基石 定义 HTTP&#xff08;英文&#xff1a;HyperText Transfer Protocol&#xff0c;缩写&#xff1a;HTTP&#xff09;&#xff0c;即超文本传输协…

【Linux】冯诺依曼体系结构-操作系统

一.冯诺依曼体系结构 我们所使用的计算机&#xff0c;如笔记本等都是按照冯诺依曼来设计的&#xff1a; 截止目前&#xff0c;我们所知道的计算机都是由一个一个的硬件组装起来的&#xff0c;这些硬件又由于功能的不同被分为了输入设备&#xff0c;输出设备&#xff0c;存储器…

mapbox进阶,使用点类型geojson加载symbol符号图层,用于标注带图标的注记,且文字居中在图标内,图标大小自适应文字

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;mapbox 从入门到精通 文章目录 一、&#x1f340;前言1.1 ☘️mapboxgl.Map 地图对象…

布隆过滤器(附带位图讲解)

提到位图&#xff0c;我们首先想到的应该是它的两面定义&#xff1a; 位图图像&#xff08;bitmap&#xff09;&#xff0c;亦称为点阵图或栅格图像&#xff0c;是由称作像素&#xff08;图片元素&#xff09;的单个点组成的。位图是指内存中连续的二进制位&#xff0c;用于对…

CC++的内存管理

目录 1、C/C内存划分 C语言的动态内存管理 malloc calloc realloc free C的动态内存管理 new和delete operator new函数和operator delete函数 new和delete的原理 new T[N]原理 delete[]的原理 1、C/C内存划分 1、栈&#xff1a;存有非静态局部变量、函数参数、返回…

【商城实战(2)】商城架构设计:从底层逻辑到技术实现

【商城实战】专栏重磅来袭&#xff01;这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建&#xff0c;运用 uniapp、Element Plus、SpringBoot 搭建商城框架&#xff0c;到用户、商品、订单等核心模块开发&#xff0c;再到性能优化、安全加固、多端适配&#xf…

USB 模块 全面解析(一)

本文是我整理的一些 USB 的学习心得&#xff0c;希望能对大家有所帮助。 文章目录 前言&#x1f352; USB 基本概述&#x1f352; USB 结构框架&#x1f349;硬件框架&#x1f349; 软件框架 &#x1f352; USB 电气信号&#x1f349; USB 硬件线路&#x1f349; 信号电平&…

xr-frame 3D Marker识别,扬州古牌坊 3D识别技术稳定调研

目录 识别物体规范 3D Marker 识别目标文件 map 生成 生成任务状态解析 服务耗时&#xff1a; 对传入的视频有如下要求&#xff1a; 对传入的视频建议&#xff1a; 识别物体规范 为提高Marker质量&#xff0c;保证算法识别效果&#xff0c;可参考Marker规范文档 Marker规…

拆一拆吉利普及高阶智驾的盲盒

吉利银河后续所有的全新和改款车型都会搭载千里浩瀚不同级别的智驾系统&#xff1b; 既然银河都标配了&#xff0c;定位更高的领克大概率也会全系标配&#xff1b; 加上极氪从去年下半年就是全系标配。 这样一来&#xff0c;就是吉利版的「全民智驾」。 一、 「千里浩瀚」&a…

2024四川大学计算机考研复试上机真题

2024四川大学计算机考研复试上机真题 2024四川大学计算机考研复试机试真题 历年四川大学计算机考研复试机试真题 在线评测&#xff1a;https://app2098.acapp.acwing.com.cn/ 分数求和 题目描述 有一分数序列&#xff1a; 2/1 3/2 5/3 8/5 13/8 21/13… 求出这个数列的前 …

基于提示驱动的潜在领域泛化的医学图像分类方法(Python实现代码和数据分析)

摘要 医学图像分析中的深度学习模型易受数据集伪影偏差、相机差异、成像设备差异等导致的分布偏移影响&#xff0c;导致在真实临床环境中诊断不可靠。领域泛化&#xff08;Domain Generalization, DG&#xff09;方法旨在通过多领域训练提升模型在未知领域的性能&#xff0c;但…

深度学习-大白话解释循环神经网络RNN

目录 一、RNN的思想 二、RNN的基本结构 网络架构 ​关键点 三、RNN的前向传播 四、RNN的挑战:梯度爆炸和梯度消失 问题分析 ​示例推导 五、LSTM:RNN的改进 核心组件 ​网络架构 3. LSTM 的工作流程 4. 数学公式总结 5. LSTM 的优缺点 ​优点 ​缺点 6. LSTM 的…

Spring统一格式返回

目录 一&#xff1a;统一结果返回 1&#xff1a;统一结果返回写法 2&#xff1a;String类型报错问题 解决方法 二&#xff1a;统一异常返回 统一异常返回写法 三&#xff1a;总结 同志们&#xff0c;今天咱来讲一讲统一格式返回啊&#xff0c;也是好久没有讲过统一格式返…

软件测试基础:功能测试知识总结

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、测试项目启动与研读需求文档 &#xff08;一&#xff09; 组建测试团队 1、测试团队中的角色 2、测试团队的基本责任 尽早地发现软件程序、系统或产品中…

wheel_legged_genesis 开源项目复现与问题记录

Reinforcement learning of wheel-legged robots based on Genesis System Requirements Ubuntu 20.04/22.04/24.04 python > 3.10 开始配置环境&#xff01; 点击releases后进入&#xff0c;下载对应最新版本的代码&#xff1a; 将下载后的代码包解压到你的自定义路径下&…

qt实践教学(编写一个代码生成工具)持续更新至完成———

前言&#xff1a; 我的想法是搭建一个和STM32cubemux类似的图形化代码生成工具&#xff0c;可以把我平时用到的代码整合一下全部放入这个软件中&#xff0c;做一个我自己专门的代码生成工具&#xff0c;我初步的想法是在下拉选框中拉取需要配置的功能&#xff0c;然后就弹出对…