ObjectMapper 启用方法已弃用

Sez*_*dın 15 java spring spring-boot objectmapper jackson-databind

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

他们说要像这样使用它。

@deprecated Since 2.13 use {@code JsonMapper.builder().enable(...)}
Run Code Online (Sandbox Code Playgroud)

但我无法使用它。

下面是我的 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;
Run Code Online (Sandbox Code Playgroud)

}

解决方案:

    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();
Run Code Online (Sandbox Code Playgroud)

M. *_*num 14

我建议将您的代码重写为

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

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

现在,对于选项 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
Run Code Online (Sandbox Code Playgroud)

当 Spring(Boot)检测JavaTime到类路径上的模块时,它将自动注册到ObjectMapper,因此无需额外添加该模块(或与此相关的序列化器)。

这些配置行应该ObjectMapper与您显式配置的配置相同。H

对于第二个选项,您可以Jackson2ObjectMapperBuilder使用参数将其注入到方法中,配置您想要的内容并build最终调用该方法。

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
Run Code Online (Sandbox Code Playgroud)

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

理论上你可以结合 1 和 2 但在你的情况下不会添加太多,只有一些代码来构造ObjectMapper.

@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();
Run Code Online (Sandbox Code Playgroud)


Nei*_*olá 6

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

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

  • DeserializationConfig从实例中获取原始数据ObjectMapper
  • MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS通过调用 with(MapperFeature... features)配置的实例来创建启用的原始配置的“副本” 。
  • ObjectMapper通过setter方法将原来的配置替换为新的配置。

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

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

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

    objectMapper.setConfig(newConfig);
}
Run Code Online (Sandbox Code Playgroud)

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