是否可以在 SpringBoot 中注册控制器特定的 ObjectMapper

RKo*_*dla 5 jackson spring-boot

我们有一个用例,其中端点返回的 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() {
    
       }
    }
Run Code Online (Sandbox Code Playgroud)

xer*_*593 9

截至 2021 年,尚未得到答复意味着仍然不可能(容易)为相同的媒体/对象/响应类型使用替代的 ObjectMapper。IE

不,不可能(容易):

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

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

但什么(简单)可能的:

是注册每个 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"));
    }
Run Code Online (Sandbox Code Playgroud)

我们可以做的:

@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;
}
Run Code Online (Sandbox Code Playgroud)

这里的技巧不是(直接)管理对象映射器,而是注册“普通映射器”,因为spring.jackson.*一旦存在 ObjectMapper bean,所有“魔法”都将被跳过。


为了实现(例如)的自定义“视图” Person引入了(2014)JSON Views