Настройка миксина Jackson в приложении Spring Boot

Я создал миксин для своего класса. Сам миксин работает нормально, это не проблема большинства людей, когда они смешивают аннотации faterxml / codehaus. Я протестировал его в модульном тесте, создав ObjectMapper «вручную», используя метод addMixIn - он работал нормально.

Я хочу использовать этот миксин для изменения json-ответов, возвращаемых моими конечными точками REST. Я пытался настроить ObjectMapper Spring Boot разными способами:

Строитель

@Bean
public Jackson2ObjectMapperBuilderCustomizer addMixin(){
    return new Jackson2ObjectMapperBuilderCustomizer() {
        @Override
        public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
            jacksonObjectMapperBuilder.mixIn(MyClass.class, MyClassMixin.class);                
        }
    };
}

Строитель:

@Bean
Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
    return new Jackson2ObjectMapperBuilder().mixIn(MyClass.class, MyClassMixin.class);
}

Конвертер:

@Bean
public MappingJackson2HttpMessageConverter configureJackson(){
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    ObjectMapper mapper = new ObjectMapper();
    mapper.addMixIn(MyClass.class, MyClassMixin.class);
    converter.setObjectMapper(mapper);
    return converter;
}

ObjectMapper:

@Autowired(required = true)
public void configureJackon(ObjectMapper jsonMapper){
    jsonMapper.addMixIn(MyClass.class, MyClassMixin.class);
}

Ничего из этого не работает.


person dkaras    schedule 05.07.2018    source источник


Ответы (2)


Это может зависеть от версии Spring Boot, но согласно Настроить Jackson ObjectMapper, достаточно определить новый Jackson2ObjectMapperBuilderCustomizer bean

Jackson2ObjectMapperBuilder контекста можно настроить с помощью одного или нескольких bean-компонентов Jackson2ObjectMapperBuilderCustomizer. Такие bean-компоненты настройки можно заказать (собственный настройщик Boot имеет порядок 0), что позволяет применять дополнительную настройку как до, так и после настройки Boot.

person Karol Dowbecki    schedule 05.07.2018

Я пробовал описанное выше, и у меня это тоже не сработало. Во время отладки я заметил, что ObjectMapper внутри конвертера сообщений был пустым.

Ссылаясь на сообщение, получите зарегистрированные конвертеры сообщений , В итоге я заменил конвертер сообщений по умолчанию для Джексона, что позволило мне настроить отображение объектов в соответствии с моими потребностями:

@SpringBootApplication
@RestController
public class MixinTest {

    public static void main(String[] args) {
        SpringApplication.run(MixinTest.class, args);
    }

    static class Person {
        private String title;
        private String name;
        private String nullField;
        private LocalDate date;

        Person(String title, String name) {
            this.title = title;
            this.name = name;
            this.date = LocalDate.now();
        }
        // getters here...
    }

    // this will exclude nullField 
    @JsonInclude(JsonInclude.Include.NON_NULL)
    interface PersonMixin {
        @JsonProperty("fullName")
        String getName();
    }

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer personCustomizer() {
        return jacksonObjectMapperBuilder ->
            jacksonObjectMapperBuilder.mixIn(Person.class, PersonMixin.class);
    }

    @Bean
    public MappingJackson2HttpMessageConverter myMessageConverter(
            // provided by Spring
            RequestMappingHandlerAdapter reqAdapter,
            Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        ObjectMapper mapper = jacksonObjectMapperBuilder
            .featuresToEnable(SerializationFeature.INDENT_OUTPUT)
            .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .modulesToInstall(new JavaTimeModule())
            .build();

        // **replace previous MappingJackson converter**
        List<HttpMessageConverter<?>> converters = 
            reqAdapter.getMessageConverters();
        converters.removeIf(httpMessageConverter ->
            httpMessageConverter.getClass()
                .equals(MappingJackson2HttpMessageConverter.class));

        MappingJackson2HttpMessageConverter jackson = new 
            MappingJackson2HttpMessageConverter(mapper);
        converters.add(jackson);
        reqAdapter.setMessageConverters(converters);
        return jackson;
    }

    @GetMapping("/test")
    public Person get() {
        return new Person("Mr", "Joe Bloggs");
    }
}

Что выводит в браузере следующее после нажатия http://localhost:8080/test:

{
    "title" : "Mr",
    "date" : "2019-09-03",
    "fullName" : "Joe Bloggs"
}

Таким образом, я смогу добавить столько настройщиков, сколько необходимо. Я уверен, что есть способ сделать это лучше. Кажется хакерским заменять такие внутренние компоненты ...

person jllangston    schedule 03.09.2019
comment
Спасибо за этот пример! Он отлично работает, мы не контролируем клиентский JDK! - person Marcello de Sales; 02.03.2021