我设置了一个类来返回自定义的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();
}
}
但是,当我从控制器方法返回一个对象时,它会使用默认的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;
}
}
当我在我的控制器上运行测试时,测试类也使用自动装配的ObjectMapper。再次提供给测试的ObjectMapper是自定义的。
所以Spring在某种程度上了解了自定义的ObjectMapper,但我的其他控制器类并没有使用它。
我已尝试为Spring启用调试日志记录,但无法在日志中看到任何有用的内容。
知道可能会发生什么,或者我应该在哪里寻找追踪问题的其他地方?
编辑:似乎有多种方法可以做到这一点,但是我尝试这样做的方式似乎是一种推荐的方法,我想让它工作这个方式 - 见https://docs.spring.io/spring-boot/docs/1.4.7.RELEASE/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper的71.3 - 我在那里误解了什么吗?
答案 0 :(得分:3)
Spring使用HttpMessageConverters呈现@ResponseBody(或来自@RestController的响应)。我认为你需要覆盖HttpMessageConverter。
您可以通过扩展WebMvcConfigurerAdapter
并覆盖以下内容来实现。
@Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
messageConverters.add(new MappingJackson2HttpMessageConverter());
super.configureMessageConverters(converters);
}
答案 1 :(得分:1)
虽然其他答案显示了实现相同结果的替代方法,但这个问题的实际答案是我已经定义了一个扩展WebMvcConfigurationSupport
的单独类。通过这样做,WebMvcAutoConfiguration
bean已被禁用,因此Spring没有获取@Primary ObjectMapper。 (在WebMvcAutoConfiguration
source中查找@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
。)
暂时删除延长WebMvcConfigurationSupport
的班级,允许@Primary
ObjectMapper
按照Spring的预期被选中并使用。
由于我无法永久删除WebMvcConfigurationSupport
扩展类,因此我在其中添加了以下内容:
@Autowired
private ObjectMapper mapper;
@Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter(mapper));
addDefaultHttpMessageConverters(converters);
super.configureMessageConverters(converters);
}
答案 2 :(得分:0)
不会破坏字符串序列化(保持顺序)的正确方法:
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
addDefaultHttpMessageConverters(converters);
HttpMessageConverter<?> jacksonConverter =
converters.stream()
.filter(converter -> converter.getClass().equals(MappingJackson2HttpMessageConverter.class))
.findFirst().orElseThrow(RuntimeException::new);
converters.add(converters.indexOf(jacksonConverter), new MappingJackson2HttpMessageConverter(objectMapper));
}
答案 3 :(得分:-1)
因为你所做的是创建一个bean Autowired
以供以后使用。 (就像你在代码中编写的那样)Spring启动使用自动配置的Jackson2ObjectMapperBuilder
来获取用于序列化的默认ObjectMapper。
因此,如果要在其余控制器上自定义ObjectMapper
序列化,则需要找到配置Jackson2ObjectMapperBuilder
的方法。有两种方法可以做到这一点:
为spring声明自己的Jackson2ObjectMapperBuilder
@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.serializationInclusion(JsonInclude.Include.NON_NULL);
// other settings you want.
return builder;
}
通过属性设置
您可以通过application.properties
进行设置。例如,如果要启用漂亮打印,请设置spring.jackson.serialization.indent_output=true
。
有关详细信息,请在此处查看: Customize the Jackson ObjectMapper