Spring-引导:不遵守 Jackson 序列化配置

Spring-Boot: Jackson serialization configuration not respected

我正在使用 spring-boot 2.5.4 并尝试全局设置 default-property-inclusion=non_null,以便空值不再出现在我的 spring 网络服务器的响应中。

我已按照 .

中所述在项目的 application.yml 中配置 spring.jackson.default-property-inclusion=non_null
spring:
  jackson:
    default-property-inclusion: non_null

不幸的是,空值仍然包含在我的控制器的输出中:

{
    "enabled": true,
    "name": "foo",
    "subdomain": null,
    "tenantId": null
}

然而,如果我将非空值直接添加到我的 dto 中,则有效:

@Data
@NoArgsConstructor
@JsonInclude(Include.NON_NULL)
public class GlobalTenantGet {

    private UUID tenantId;

    private String name;

    private String subdomain;

    private boolean enabled;
}

屈服

{
    "enabled": true,
    "name": "foo"
}

符合预期。

问题

为什么在 dto 上本地配置 @JsonInclude 会导致 null 属性按预期消失,但为什么配置 spring.jackson.default-property-inclusion=non_null 却没有相同的效果?

附加信息

1。调试

org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.JacksonObjectMapperConfiguration#jacksonObjectMapper 中设置断点表明,在 application.yaml 中配置的属性确实到达了 jackson:

2。在控制器

中自动装配ObjectMapper

在我的控制器中自动装配 ObjectMapper 并直接通过 objectMapper.writeValueAsString() 序列化我的对象时,我得到了预期的行为。

其他配置方式ObjectMapper

这些主要是回复的回答

1。使用@primary

我有一个

@Configuration
public class ObjectMapperConfiguration {

    @Primary
    @Bean
    public ObjectMapper objectMapper() {
        final var om = new ObjectMapper();
        om.setSerializationInclusion(Include.NON_NULL);
        return om;
    }
}

输出中仍然包含空属性

2。 Jackson2ObjectMapperBuilderserializationInclusion

@Configuration
public class ObjectMapperConfiguration {
    @Bean
    public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
        return new Jackson2ObjectMapperBuilder().serializationInclusion(JsonInclude.Include.NON_NULL);
    }
}

仍然产量

{
    "enabled": true,
    "name": "foo",
    "subdomain": null,
    "tenantId": null
}

3。定义 MappingJackson2HttpMessageConverter

@Configuration
public class ObjectMapperConfiguration {
    @Bean
    public MappingJackson2HttpMessageConverter messageMappingConverter() {
        final var om = new ObjectMapper();
        om.setSerializationInclusion(Include.NON_NULL);
        return new MappingJackson2HttpMessageConverter(om);
    }
}

仍然没有布埃诺:-(

有几种可能的方法可以解决这个问题,其中一些在此处有明确的解释:https://www.baeldung.com/spring-boot-customize-jackson-objectmapper

通常你可以:

  1. 通过创建自定义 ObjectMapper bean 并将其标记为 @Primary 来覆盖默认值 ObjectMapper(最简单的方法,但会严重影响您的应用程序,因为所有 ObjectMapper 你在代码中注入的实例将默认使用这个,这对你来说可能是好是坏)

  2. Jackson2ObjectMapperBuilder 定义自定义 bean 并在此构建器上设置适当的 serializationInclusion

  3. 在 Spring 中注册自定义 HTTP 消息转换器,它将通过为 MappingJackson2HttpMessageConverter 定义 bean 使用自定义 ObjectMapper(此转换器的构造函数接受 ObjectMapper,因此您可以通过在那里正确配置映射器)

看来 @EnableWebMvc 是罪魁祸首。我有一个看起来像这样的 WebMvcConfigurer

@Configuration
@EnableWebMvc // <----- this is the culprit!
public class WebConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedMethods("OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE")
                .allowedOrigins("example.com")
                .allowedHeaders("*");
    }

    @Bean
    public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }

    @Bean
    public InternalResourceViewResolver defaultViewResolver() {
        return new InternalResourceViewResolver();
    }

}

注释掉 @EnableWebMvc 允许一切按预期工作。