spring-boot - 是否可以在 SpringBoot 中注册控制器特定的 ObjectMapper
问题描述
我们有一个用例,其中端点返回的 JSON 必须根据端点进行不同的序列化。是否可以注册两个单独的 ObjectMapper bean 并指定哪个用于特定控制器?例如,如果我定义了一个如下所示的自定义 objectmapper,我是否可以要求 Spring Boot 使用此映射器仅序列化 ControllerTwo 的返回对象,但使用 default/Primary objectmapper 序列化从 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() {
}
}
解决方案
截至 2021 年,未答复意味着仍然不可能(容易)为相同的媒体/对象/响应类型使用替代 ObjectMapper。IE
不,不可能(容易):
... 在 SpringBoot 中注册控制器特定的 ObjectMapper
(..不是没有“重新实现”一半的spring-web)。
但是什么是(容易的)可能的:
是为每个 java 和媒体类型注册自定义 (组合!+ 媒体类型的通配符)!(除了弹簧配置的“默认对象映射器”)ObjectMapper
和:
//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(直接)管理对象映射器,而是注册“普通映射器”,因为spring.jackson.*
一旦存在ObjectMapper bean,所有“魔法”都将被跳过。
为了实现 (eg) 的自定义“视图” Person
,spring引入了 (2014) JSON Views。
推荐阅读
- elasticsearch - Elasticsearch 两个 multi_match 查询
- c# - 最后一个 for 循环没有按我的意愿执行
- format - 货币的 smartsheet API 单元格格式
- python - PyNaCl 中的 64 字节密钥
- javascript - Javascript 正则表达式替换空格和 html
- r - 过滤传单地图,其中包括使用串扰的集群
- angular - Angular creating divs with ngFor on an array of objects: How to refresh add another div when another object is added to the Array
- python - 检查变量在一段时间内发生了多少变化
- java - 如何通过Java程序执行`docker exec -it netvertex bash`
- c++ - 进程返回 -1073741819 (0xC0000005) 编译 C++ 时钟时出错