【SpringBoot实战专题】「开发实战系列」全方位攻克你的技术盲区之Spring定义Jackson转换Null的方法和实现案例

简介: 【SpringBoot实战专题】「开发实战系列」全方位攻克你的技术盲区之Spring定义Jackson转换Null的方法和实现案例

背景

在Spring MVC中配置JSON转换器时,当需要全局控制将某些JSON返回值的key转换为一些默认值时,可以通过实现一个自定义的序列化器(Serializer)来实现这个功能。现在,我们来深入了解Spring MVC的整体处理流程,以确定在哪个步骤进行实现和调整。 我们先来总结数量一下整个流程:

  1. 用户发送请求,由Spring的前端控制Servlet DispatcherServlet捕获。
  2. DispatcherServlet解析请求URL,并根据URI获取与之相关的Handler和拦截器配置。
  3. DispatcherServlet选择合适的HandlerAdapter来执行Handler(Controller)。在此过程中,也会执行拦截器的preHandler方法。
  4. 提取请求中的模型数据(通过MessageConverter对于入参进行转换)并填充Handler的参数,开始执行Handler。
  5. 执行完成后,返回一个包含Model和View信息的ModelAndView对象。
  6. 根据ModelAndView选择合适的ViewResolver,将其返回给DispatcherServlet。
  7. ViewResolver将Model和View结合起来,进行视图渲染。
  8. 最终将渲染结果返回给客户端(响应的数据转换则通过MessageConverter完成)

MessageConverter

对于JSON转换,涉及到MessageConverter的工作,通过在Spring MVC处理流程中的适当步骤实现自定义序列化器,我们能够全局控制JSON返回值的key,确保它们在需要时转换为指定的默认值。这种方式提供了灵活性和可定制性,使开发者能够更好地适应不同的业务需求。 MappingJackson2HttpMessageConverter是Spring框架中提供的一个HTTP消息转换器,用于在Spring MVC中进行JSON与Java对象之间的转换。它基于Jackson库,利用Jackson提供的功能进行JSON的序列化和反序列化,接下来我们就针对于它进行实现。

使用Jackson原生方式处理空字段(次重点方案)

当返回字段为null时需要进行处理,可以通过配置ObjectMapper来选择合适的处理方式。以下是几种常见的处理方式及其配置方式:

ObjectMapper的配置选项

使得ObjectMapper在将Java对象转换为JSON字符串时,仅包含字段值不为null的属性。对于为null的属性,它们将被忽略并不会显示在生成的JSON中。

java

复制代码

// 创建ObjectMapper实例
ObjectMapper objectMapper = new ObjectMapper();
// 配置ObjectMapper处理返回字段为null的方式
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);  // 字段均包含在结果JSON中,无论是否为null
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);  // 字段的值不为null时,才会包含在结果JSON中
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);  // 字段的值与其默认值不相等时,才会包含在结果JSON中
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);  // 字段的值不为null且不为空时,才会包含结果JSON中
// 使用配置好的ObjectMapper进行对象转换
YourObject yourObject = ...;  // 要转换的对象
String json = objectMapper.writeValueAsString(yourObject);  // 将对象转换为JSON字符串

通过使用注解的方式

使用注解可以更精确地控制每个类或属性的处理方式。

java

复制代码

@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@JsonInclude(JsonInclude.Include.NON_EMPTY)

通过调用setSerializationInclusion方法并传入相应的JsonInclude.Include枚举值,可以配置ObjectMapper处理返回字段为null时的方式。可以根据具体需求选择适合的处理方式。

MappingJackson2HttpMessageConverter(重点方案)

对于SpringMVC,我们会采用MappingJackson2HttpMessageConverter可以将Java对象转换为JSON格式的响应体,并将JSON格式的请求体转换为对应的Java对象。它支持多种媒体类型,如application/json、text/json等。

创建MappingJackson2HttpMessageConverter

在Spring MVC中配置MappingJackson2HttpMessageConverter可以通过以下两种方式:Xml配置和Javaconfig配置

XML配置

下面展示了如何在applicationContext.xml文件中进行XML配置来实现对MappingJackson2HttpMessageConverter 的定义,并通过元素设置了supportedMediaTypes属性:

xml

复制代码

<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="supportedMediaTypes">
        <list>
            <value>application/json</value>
            <!-- 可以添加其他支持的媒体类型 -->
        </list>
    </property>
    <!-- 其他配置属性 -->
</bean>

在上述配置中,我们使用元素定义了MappingJackson2HttpMessageConverter的bean,并指定了其类名org.springframework.http.converter.json.MappingJackson2HttpMessageConverter,通过元素来设置supportedMediaTypes属性。通过元素来指定一个媒体类型列表,其中每个类型由元素表示。在示例中,我们设置了一个值为application/json的媒体类型。这样就可以将Java对象转换为JSON,并以指定的媒体类型返回给客户端。

Java配置

在Java配置中,我们可以使用@Bean注解创建MappingJackson2HttpMessageConverter的bean,并在方法中进行相同的配置。此外,我们还可以使用Charset.forName("UTF-8")来替代java.nio.charset.StandardCharsets.UTF_8来创建MediaType。具体示例如下:

java

复制代码

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        // 配置媒体类型
        converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON));
        // 其他配置...
        converters.add(converter);
    }
}

MappingJackson2HttpMessageConverter整合ObjectMapper的配置

在上面我们定义了一个 MappingJackson2HttpMessageConverter bean,并设置了 supportedMediaTypes 属性为"application/json",以支持在 Spring MVC 中将 Java 对象转换为 JSON 并返回给客户端。

在这个基础知识,我们加入了最早介绍的 ObjectMapper bean,并设置其 serializationInclusion 属性为 NON_NULL,这将使得序列化时排除掉值为null的字段。

XML配置

xml

复制代码

<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="supportedMediaTypes">
        <list>
            <value>application/json;charset=UTF-8</value>
        </list>
    </property>
    <property name="objectMapper">
        <bean class="com.fasterxml.jackson.databind.ObjectMapper">
            <property name="serializationInclusion">
                <value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
            </property>
        </bean>
    </property>
</bean>

JavaConfig配置

通过mappingJacksonHttpMessageConverter方法创建了一个MappingJackson2HttpMessageConverter的实例,并设置了支持的媒体类型为application/json;charset=UTF-8。

java

复制代码

@Configuration
public class WebConfig {
    @Bean
    public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        // 配置支持的媒体类型为application/json;charset=UTF-8
        converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));
        // 配置ObjectMapper,设置serializationInclusion为NON_NULL
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        converter.setObjectMapper(objectMapper);
        return converter;
    }
}

创建了一个ObjectMapper实例,并配置了其serializationInclusion为NON_NULL,然后将该ObjectMapper设置到MappingJackson2HttpMessageConverter中。

自定义的null处理类注解

自定义的 DetfaultNullJsonSerializer,它是一个继承自 JsonSerializer<Object> 的序列化器,用于处理值为null的情况。在 serialize 方法中,我们将使用自定义的 JsonNullDef 对象来替代值为null的字段进行序列化。

java

复制代码

public class DetfaultNullJsonSerializer extends JsonSerializer<Object> {
    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException, JsonProcessingException {
        jgen.writeObject(new JsonNullDef());
    }
}
class JsonNullDef {
    private List<String> def = new ArrayList<>();
    public List<String> getDef() {
        return def;
    }
    public void setDef(List<String> def) {
        this.def = def;
    }
}

因此,我们可以通过自定义ObjectMapper和注册自定义的序列化器来在转换过程中添加我们需要的控制逻辑。上述的示例代码展示了如何在WebConfig配置类中实现这一点,通过注册自定义的序列化器实现对特定字段null值的转换为默认值。

JsonNullDef 类中,我们定义了一个包含一个名为 def 的列表字段,用于存储默认值。通过这个自定义的null处理类,我们可以在值为null的字段处提供一个默认值,从而避免在序列化时出现null值。

方案1:使用注解

在需要使用自定义序列化器的类或对象上,通过注解或方法来指定使用 DetfaultNullJsonSerializer,例如在 MyData 类中使用注解:

java

复制代码

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
public class MyData {
    @JsonSerialize(nullsUsing = DetfaultNullJsonSerializer.class)
    private String name;
    @JsonSerialize(nullsUsing = DetfaultNullJsonSerializer.class)
    private String description;
    // 其他字段和方法...
   // 构造函数、getter和setter方法...
}

除了直接用到了注解上,还可以定义到序列化器上面,方便控制和整合到MappingJackson2HttpMessageConverter中。

方案1:序列化器

创建一个自定义的 ObjectMapper 并注册自定义的序列化器:

java

复制代码

@Configuration
public class WebConfig {
  public ObjectMapper objectMapper() {
          ObjectMapper objectMapper = new ObjectMapper();
          SimpleModule module = new SimpleModule();
          module.addSerializer(Object.class, new DetfaultNullJsonSerializer());
          objectMapper.registerModule(module);
          return objectMapper;
  }
    @Bean
    public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        // 配置支持的媒体类型为application/json;charset=UTF-8
        converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));
        converter.setObjectMapper(objectMapper());
        return converter;
    }
}

总结一下

用自定义的DetfaultNullJsonSerializer,在类或属性上使用@JsonSerialize(nullsUsing = DetfaultNullJsonSerializer.class)注解指定使用该序列化器,以及在配置类中创建并注册自定义的ObjectMapper,将自定义序列化器与ObjectMapper关联。在代码中使用该ObjectMapper实现对象的序列化和反序列化操作。这样,你就可以灵活地控制值为null的字段的处理方式。



目录
打赏
0
0
0
0
379
分享
相关文章
|
7天前
|
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
40 0
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 三大核心组件
本课程介绍如何在Spring Boot中集成Shiro框架,主要讲解Shiro的认证与授权功能。Shiro是一个简单易用的Java安全框架,用于认证、授权、加密和会话管理等。其核心组件包括Subject(认证主体)、SecurityManager(安全管理员)和Realm(域)。Subject负责身份认证,包含Principals(身份)和Credentials(凭证);SecurityManager是架构核心,协调内部组件运作;Realm则是连接Shiro与应用数据的桥梁,用于访问用户账户及权限信息。通过学习,您将掌握Shiro的基本原理及其在项目中的应用。
41 0
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——发布/订阅消息的生产和消费
本文详细讲解了Spring Boot中ActiveMQ的发布/订阅消息机制,包括消息生产和消费的具体实现方式。生产端通过`sendMessage`方法发送订阅消息,消费端则需配置`application.yml`或自定义工厂以支持topic消息监听。为解决点对点与发布/订阅消息兼容问题,可通过设置`containerFactory`实现两者共存。最后,文章还提供了测试方法及总结,帮助读者掌握ActiveMQ在异步消息处理中的应用。
53 0
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ集成
本文介绍了在 Spring Boot 中集成 ActiveMQ 的详细步骤。首先通过引入 `spring-boot-starter-activemq` 依赖并配置 `application.yml` 文件实现基本设置。接着,创建 Queue 和 Topic 消息类型,分别使用 `ActiveMQQueue` 和 `ActiveMQTopic` 类完成配置。随后,利用 `JmsMessagingTemplate` 实现消息发送功能,并通过 Controller 和监听器实现点对点消息的生产和消费。最后,通过浏览器访问测试接口验证消息传递的成功性。
19 0
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
29 0
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
34 0
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
本课主要讲解Spring Boot项目中的属性配置方法。在实际开发中,测试与生产环境的配置往往不同,因此不应将配置信息硬编码在代码中,而应使用配置文件管理,如`application.yml`。例如,在微服务架构下,可通过配置文件设置调用其他服务的地址(如订单服务端口8002),并利用`@Value`注解在代码中读取这些配置值。这种方式使项目更灵活,便于后续修改和维护。
15 0
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— application.yml 中对日志的配置
在 Spring Boot 项目中,`application.yml` 文件用于配置日志。通过 `logging.config` 指定日志配置文件(如 `logback.xml`),实现日志详细设置。`logging.level` 可定义包的日志输出级别,例如将 `com.itcodai.course03.dao` 包设为 `trace` 级别,便于开发时查看 SQL 操作。日志级别从高到低为 ERROR、WARN、INFO、DEBUG,生产环境建议调整为较高级别以减少日志量。本课程采用 yml 格式,因其层次清晰,但需注意格式要求。
35 0
|
12天前
|
基于SpringBoot的Redis开发实战教程
Redis在Spring Boot中的应用非常广泛,其高性能和灵活性使其成为构建高效分布式系统的理想选择。通过深入理解本文的内容,您可以更好地利用Redis的特性,为应用程序提供高效的缓存和消息处理能力。
119 79
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 的使用
本文介绍了 Thymeleaf 在 Spring Boot 项目中的使用方法,包括访问静态页面、处理对象和 List 数据、常用标签操作等内容。通过示例代码展示了如何配置 404 和 500 错误页面,以及如何在模板中渲染对象属性和列表数据。同时总结了常用的 Thymeleaf 标签,如 `th:value`、`th:if`、`th:each` 等,并提供了官方文档链接以供进一步学习。
50 0
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 的使用

热门文章

最新文章