【问题标题】:Custom ObjectMapper ignored after migration to Spring Boot 2迁移到 Spring Boot 2 后忽略自定义 ObjectMapper
【发布时间】:2019-04-21 11:48:48
【问题描述】:

在迁移到 Spring Boot 2.1.0 之前,我通过扩展 WebMvcConfigurerAdapter 配置了以下 ObjectMapper,按预期工作。

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {

private static final ObjectMapper objectMapper = buildObjectMapper();

private static ObjectMapper buildObjectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE);
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    mapper.configOverride(LocalDate.class).
            setFormat(JsonFormat.Value.forPattern("yyyy-MM-dd"));
    mapper.registerModule(new JavaTimeModule());
    return mapper;
}

public static ObjectMapper getObjectMapper() {
    return objectMapper;
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(new MappingJackson2HttpMessageConverter(objectMapper)); // JSON converter
}
}

但是在迁移之后我可以看到设置 PropertyNamingStrategy 似乎没有任何效果,我的应用程序仍然希望 JSON 字段的格式与默认值匹配(例如,如预期的那样需要“bloodType”而不是“blood-type”)。

我认为映射器本身没有任何问题,因为我使用静态getObjectMapper 通过RestAssuredConfigREST Assured 共享同一个实例,并且如果我更新,似乎仍然按预期运行我的自定义映射器到默认行为(评论setPropertyNamingStrategy)一切似乎都按预期工作。

编辑 1

事实上,我的整个映射器都被忽略了,我尝试更改LocalDate 格式,也没有任何区别。更新标题以更好地反映问题。

【问题讨论】:

  • 我认为你的映射器 propertyNamingStrategy 不是通过 Spring Boot 应用程序获取的,而是从休眠 propertyNamingStrategy 获取的,你应该试试这个。 spring.jpa.hibernate.naming.physical-strategy=com.example.MyPhysicalNamingStrategy 参考:docs.spring.io/spring-boot/docs/current/reference/html/…

标签: java spring-mvc spring-boot jackson


【解决方案1】:

我认为你的映射器propertyNamingStrategy 不是通过spring boot application 它从休眠propertyNamingStrategy 得到的,你应该试试这个。

spring.jpa.hibernate.naming.physical-strategy=com.example.MyPhysicalNamingStrategy

参考:docs.spring.io/spring-boot/docs/current/reference/html/…

或者:

   @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter<?> converter : converters) {
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                MappingJackson2HttpMessageConverter jsonMessageConverter = (MappingJackson2HttpMessageConverter) converter;
                ObjectMapper objectMapper = jsonMessageConverter.getObjectMapper();
                mapper.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE);
                break;
            }
        }
    }

【讨论】:

  • 问题可能出现在解析的 JSON 请求上,在 REST 控制器上,解析的对象错过了与默认格式不匹配的字段。在这一点上不应该涉及 Hibernate,但也许有一些 Spring 魔法,无论如何你知道如何设置这个属性来拥有 KEBAB_CASE 策略,所以我可以测试你的建议吗?对我来说,这个属性应该用于不同的东西,这就是我感到困惑的原因。
  • 您可以尝试我的建议并提供您的反馈。我认为它会起作用。
  • 我已经尝试了你的第二个建议,我用你的 extendMessageConverters 替换了 configureMessageConverters 并且仍然是同样的问题,但是在这样做时我决定尝试更改我的 LocalDate 格式以查看是否它会有任何区别,而且这也被忽略了。我认为这是一个更普遍的配置问题,因为我的自定义 ObjectMapper 似乎完全被忽略了。我正在查看最新的文档,看看我做错了什么,到目前为止,我还没有在 Spring Boot 2 文档上发现这些点有很大的不同。
【解决方案2】:

我的问题通过添加 @EnableWebMvc 注释得到解决,根据文档,它完全控制了 Spring MVC,这不是我最初想要的,但至少是有意义的。我不清楚为什么在我迁移到 Spring Boot 2 之前它可以工作,以及为什么扩展 Spring MVC 行为不再起作用。

如果有一个答案可以对此进行很好的解释,我将不胜感激,理想情况下会避免@EnableWebMvc 完全覆盖。

编辑 1

通常你会为 Spring MVC 应用程序添加 @EnableWebMvc,但 Spring Boot 在看到 spring-webmvc 时会自动添加 类路径。

参考:https://spring.io/guides/gs/serving-web-content/

不幸的是,这对我来说不是一个完整的解释,因为我可以在我的类路径中看到 spring-webmvc:5.1.2.RELEASE

考虑到使用@EnableWebMvc 或为ObjectMapper 配置一个@Bean 可以按预期工作,我会将其标记为已回答。

我仍然想知道为什么需要@EnableWebMvc,考虑到根据文档不应该这样做。

【讨论】:

  • 能否找到避免@EnableWebMvc 完全覆盖的解决方案?
  • 我找不到需要@EnableWebMvc 的原因,所以我最终为我正在处理的项目删除了@EnableWebMvc,并使用了ObjectMapper bean。我没有任何计划回到这个问题,但我想了解为什么它一开始就不起作用,因为我的整个包装器都被忽略了,无论如何你可以检查我在项目中做了什么,看看是否它有任何帮助:github.com/taizel/donor-calendar/tree/master/webapp/src/main/…
  • 感谢您的样品。由于在经过测试的 DTO 上存在剩余的 @JsonFormat,我正面临自引起的问题。最后,我只需提供一个Jackson2ObjectMapperBuilderCustomizer bean 就能够实现我所需要的。
猜你喜欢
  • 2023-03-15
  • 2019-09-23
  • 2021-05-13
  • 2018-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多