我们有一个用例,端点返回的 JSON 必须根据端点进行不同的序列化。是否可以注册两个单独的 ObjectMapper bean 并指定将哪一个用于特定控制器?例如,如果我定义如下所示的自定义对象映射器,我可以要求 Spring Boot 使用此映射器仅序列化从 ControllerTwo 返回的对象,但使用默认/主对象映射器序列化从 ContorllerOne 返回的对象吗?
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper mapper = builder.build();
return mapper;
}
@Bean
public ObjectMapper objectMapperCustom(Jackson2ObjectMapperBuilder builder) {
ObjectMapper mapper = builder.build();
//customize mapper
return mapper;
}
@RestController
public class ControllerOne {
@GetMapping("/personNew/{id}")
public Person getMyClass() {
}
}
@RestController
public class ControllerTwo {
@GetMapping("/personOld/{id}")
public Person getMyClass() {
}
}
不,不可能(容易):
...在SpringBoot中注册控制器特定的ObjectMapper(..不是没有“重新实现”一半的
spring-web)。
但是是什么(简单)可能:
是注册customObjectMapper
//no bean
private ObjectMapper fooMapper() {
return new ObjectMapper()
.configure(SerializationFeature.WRAP_ROOT_VALUE, true)
.configure(SerializationFeature.INDENT_OUTPUT, false)
.setDateFormat(new SimpleDateFormat("dd.MM.yyyy hh:mm:ss"));
}
//no bean
private ObjectMapper barMapper() {
return new ObjectMapper()
.configure(SerializationFeature.WRAP_ROOT_VALUE, true)
.configure(SerializationFeature.INDENT_OUTPUT, false)
.setDateFormat(new SimpleDateFormat("MM/dd/yyyy K:mm:ss a"));
}
我们可以做:
@Bean //overwrites the autoconfigured
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(
@Autowired ObjectMapper objectMapper // auto- and property configured, when no (alternative) ObjectMapper bean is defined.
) {
MappingJackson2HttpMessageConverter bean = new MappingJackson2HttpMessageConverter();
// set "the default":
bean.setObjectMapper(objectMapper);
// register custom:
bean.registerObjectMappersForType(Foo.class, m -> { //!!
m.put(MediaType.APPLICATION_JSON, fooMapper());
// ...
});
bean.registerObjectMappersForType(Bar.class, m -> {
m.put(MediaType.APPLICATION_JSON, barMapper());
});
return bean;
}
这里的技巧是不是让spring(直接)管理对象映射器,而是注册“普通映射器”,因为一旦存在ObjectMapper bean,所有“spring.jackson.*
魔法”都将被跳过。
Person
的自定义“视图”,引入了spring(2014)JSON Views。
WebMvcConfigurer#configureMessageConverters
对其进行自定义。使用像Guava ClassPath 这样的东西,你甚至可以对包和子包中的所有类型执行此操作:
@Configuration
class MyConfig : WebMvcConfigurer {
override fun configureMessageConverters(converters: MutableList<HttpMessageConverter<*>>) {
// find the converter you are interested in
val converter: MappingJackson2HttpMessageConverter = converters.first { MappingJackson2HttpMessageConverter::class.java == it.javaClass } as MappingJackson2HttpMessageConverter
// find all the classes you want to use a custom object mapper for
val classes = ClassPath.from(ClassLoader.getSystemClassLoader()).getTopLevelClassesRecursive("my.custom.package")
classes.forEach {
converter.registerObjectMappersForType(it.load()) { m ->
m[MediaType.APPLICATION_JSON] = myCustomerObjectMapper()
}
}
}
}