繁体   English   中英

在 Spring 引导应用程序中配置 Jackson mixin

[英]Configuring Jackson mixin in Spring Boot application

我为我的 class 创建了一个 mixin。 mixin 本身工作正常,这不是大多数人在混合 faterxml/codehaus 注释时遇到的问题。 我在单元测试中对其进行了测试,在使用 addMixIn 方法时“手动”创建了 ObjectMapper - 它工作得很好。

我想使用该 mixin 来修改从我的 REST 端点返回的响应 json。 我尝试以多种不同方式自定义 Spring Boot 的 ObjectMapper:

BuilderCustomizer:

@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;
}

对象映射器:

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

这些都不起作用。

从 Spring Boot 2.7 开始,内置了对 mixins 的支持。

添加以下注释:

@JsonMixin(MyClass::class)
class MyClassMixin{

将在自动配置的ObjectMapper中注册 mixin。

这可能取决于Spring Boot版本,但是根据Customize Jackson ObjectMapper的定义,定义一个新的Jackson2ObjectMapperBuilderCustomizer bean就足够了

上下文的Jackson2ObjectMapperBuilder可以由一个或多个Jackson2ObjectMapperBuilderCustomizer bean进行自定义。 可以对此类定制器bean进行排序(Boot自己的定制器的顺序为0),从而可以在Boot定制之前和之后应用其他定制。

我已经尝试了上述方法,但对我也不起作用。 调试时,我注意到消息转换器内的ObjectMapper为空。

关于发布注册消息转换器的文章 ,我最终替换了Jackson的默认消息转换器,从而允许我根据需要自定义对象映射器:

@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"
}

这样,我应该能够根据需要添加尽可能多的定制器。 我敢肯定有更好的方法可以做到这一点。 像这样更换内部零件似乎很困难...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM