为什么Spring Boot不使用@Primary Jackson ObjectMapper在rest控制器上进行JSON序列化?

Dan*_*Dan 6 spring-boot jackson2

我有一个设置返回自定义ObjectMapper的类。据我所知,让Spring Boot使用此ObjectMapper的正确方法是将其声明为@Primary。

@Configuration
public class MyJacksonConfiguration {

    @Bean
    @Primary
    public ObjectMapper objectMapper() {
        return Jackson2ObjectMapperBuilder
            .json()
            .findModulesViaServiceLoader(true)
            .mixIn(Throwable.class, ThrowableMixin.class)
            .featuresToDisable(
                    WRITE_DATES_AS_TIMESTAMPS)
            .serializationInclusion(
                    Include.NON_ABSENT)
            .build();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我从控制器方法返回对象时,它将使用默认的Jackson ObjectMapper配置进行序列化。

如果我在控制器上添加一个显式的ObjectMapper并调用writeValueAsString,则可以看到该ObjectMapper是我希望Spring Boot使用的自定义对象。

@RestController
public class TestController {

    @Autowired
    private TestService service;

    @Autowired
    private ObjectMapper mapper;

    @GetMapping(value = "/test", produces = "application/json")
    public TestResult getResult() {

        final TestResult ret = service.getResult();

        String test = "";
        try {
            test = mapper.writeValueAsString(ret);
            // test now contains the value I'd like returned by the controller!
        } catch (final JsonProcessingException e) {
            e.printStackTrace();
        }

        return ret;
    }
}
Run Code Online (Sandbox Code Playgroud)

当我在控制器上运行测试时,测试类还使用自动装配的ObjectMapper。同样,提供给测试的ObjectMapper是自定义对象。

因此,Spring在某种程度上了解自定义的ObjectMapper,但是我的rest控制器类并未使用它。

我曾尝试为Spring启用调试日志记录,但在日志中看不到任何有用的东西。

任何想法可能会发生什么,或者我应该在哪里寻找问题的根源?

编辑:似乎有多种方法可以执行此操作,但是我尝试执行的方法似乎是推荐的方法,我希望使它以这种方式工作-请参阅https://docs.spring的 71.3 .io / spring-boot / docs / 1.4.7.RELEASE / reference / html / howto-spring-mvc.html#howto-customize-the-jackson-objectmapper-我误会了那里的东西吗?

Dan*_*Dan 5

Whilst the other answers show alternative ways of achieving the same result, the actual answer to this question is that I had defined a separate class that extended WebMvcConfigurationSupport. By doing that the WebMvcAutoConfiguration bean had been disabled and so the @Primary ObjectMapper was not picked up by Spring. (Look for @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) in the WebMvcAutoConfiguration source.)

Temporarily removing the class extending WebMvcConfigurationSupport allowed the @Primary ObjectMapper to be picked up and used as expected by Spring.

As I couldn't remove the WebMvcConfigurationSupport extending class permanently, I instead added the following to it:

@Autowired
private ObjectMapper mapper;

@Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {
    converters.add(new MappingJackson2HttpMessageConverter(mapper));
    addDefaultHttpMessageConverters(converters);
    super.configureMessageConverters(converters);
}
Run Code Online (Sandbox Code Playgroud)