是否可以在SpringBoot中注册Controller特定的ObjectMapper

问题描述 投票:0回答:2

我们有一个用例,端点返回的 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() {
    
       }
    }
spring-boot jackson
2个回答
9
投票
截至 2021 年,尚未得到答复意味着仍然不可能(容易)为相同的媒体/对象/响应类型使用替代的 ObjectMapper。即

不,不可能(容易):

...在SpringBoot中注册控制器特定的ObjectMapper

(..不是没有“重新实现”一半的

spring-web

但是

是什么(简单)可能:

是注册

customObjectMapper

每个java-和媒体类型(组合!+媒体类型的通配符)! (除了弹簧配置的“默认对象映射器”)

与:

//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; }
这里的技巧是

不是springspring.jackson.*

魔法”都将被跳过。


为了实现(例如)

Person

的自定义“视图”,引入了
springJSON Views


0
投票
覆盖现有消息转换器的另一种方法是通过

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() } } } }
    
© www.soinside.com 2019 - 2024. All rights reserved.