ObjectMapper 启用方法已弃用

ObjectMapper enable method is deprecated

我正在升级我的项目版本,我目前使用的是 jackson-databind-2.13.0 .但我注意到 ObjectMapper 的 enable 方法已被弃用。

他们说要这样用。

@deprecated Since 2.13 use {@code JsonMapper.builder().enable(...)}

但是我无法使用它。

下面是我的 ObjectMapper 实例创建代码。我该如何改变?

      @Bean(name = {"objectMapper"})
      @Primary
      ObjectMapper objectMapper() {
        return newObjectMapper();
      }

  public static ObjectMapper newObjectMapper() {
    ObjectMapper objectMapper =
        new ObjectMapper()
            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
            .setSerializationInclusion(JsonInclude.Include.NON_NULL)
            .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer());
javaTimeModule.addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer());
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer());
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
objectMapper
    .registerModule(javaTimeModule)
    .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

return objectMapper;

}

解决方案:

    ObjectMapper objectMapper = JsonMapper
    .builder()
    .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
    .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
    .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
    .serializationInclusion(Include.NON_NULL).build();

我建议将您的代码重写为

  1. 删除此 bean 并使用完全 Spring 配置的引导 ObjectMapper(名称为 jacksonObjectMapper
  2. 使用 Jackson2ObjectMapperBuilder 创建 ObjectMapper 的实例。

所有这些解决方案都隐藏了构建 ObjectMapper 的复杂部分,并且还将(正确地)构建它的负担交给 Spring 引导团队,而不是你。

现在,对于选项 1,您需要删除 @Bean 并将以下内容放入 application.properties

spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false

spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=false
spring.jackson.deserialization.ACCEPT_SINGLE_VALUE_AS_ARRAY=true

spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_PROPERTIES=true

spring.jackson.defaultPropertyInclusion=NON_NULL

当 Spring(引导)在类路径上检测到 JavaTime 模块时,它将自动注册到 ObjectMapper,因此无需额外添加(或序列化程序)那很重要)。

这些配置行应该与您明确配置的配置相同 ObjectMapper。 H

对于第二个选项,您可以使用参数将 Jackson2ObjectMapperBuilder 注入方法,在那里配置您想要的东西,最后调用 build 方法。

@Bean(name = {"objectMapper"})
@Primary
ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    return newObjectMapper(builder);
}

public static ObjectMapper newObjectMapper(Jackson2ObjectMapperBuilder builder) {
   return builder
            .serializationInclusion(NON_NULL)
            .failOnEmptyBeans(false)
            .failOnUnknownProperties(false)
           .featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
           .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();

您仍然不需要注册 JavaTime 模块,因为它仍在为您自动检测。

理论上您可以将 1 和 2 结合起来,但在您的情况下不会增加太多,只需一些代码来构造 ObjectMapper

@Bean(name = {"objectMapper"})
@Primary
ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    return newObjectMapper(builder);
}

public static ObjectMapper newObjectMapper(Jackson2ObjectMapperBuilder builder) {
   return builder.build();
}

我在尝试通过 MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS 启用 Enum 不区分大小写的反序列化时遇到了类似的问题。

在我的例子中,由于 ObjectMapper 之前是由外部源构建的,因此无法切换到构建器方法。所以唯一的选择是直接修改 ObjectMapper 反序列化配置。 寻找替代方案以避免弃用 API objectMapper.enable(MappedFeature... f) 我找到了一个解决方法...

  • ObjectMapper 实例获取原始 DeserializationConfig
  • 正在创建 'copy' 原始配置 MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS 通过调用启用 with(MapperFeature... features) 在配置的实例上。
  • 用新配置替换ObjectMapper原来的配置 setter 方法。

这也适用于 SerializationConfig,它是一种在不使用已弃用的 API 的情况下修改已构建的 ObjectMapper 配置的方法。

public void customizeMapper(ObjectMapper objectMapper) {
    final DeserializationConfig originalConfig = objectMapper.getDeserializationConfig();

    final DeserializationConfig newConfig = originalConfig.with(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);

    objectMapper.setConfig(newConfig);
}

注意:使用Jackson的builder绝对是更好的解决方案。仅当无法使用生成器时才考虑此方法。