How to customise Jackson in Spring Boot 1.4
Asked Answered
F

3

24

I've been unable to find examples of how to use Jackson2ObjectMapperBuilderCustomizer.java in spring boot 1.4 to customise the features of Jackson.

The doco for customising Jackson in boot 1.4 - https://docs.spring.io/spring-boot/docs/1.4.x/reference/htmlsingle/#howto-customize-the-jackson-objectmapper

My configuration works, although I am unsure if this is the correct way to customise the object mapper using Jackson2ObjectMapperBuilderCustomizer.java

@Configuration
public class JacksonAutoConfiguration {

    @Autowired
    private Environment env;

    @Bean
    public Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder(
        List<Jackson2ObjectMapperBuilderCustomizer> customizers) {
        Jackson2ObjectMapperBuilder builder = configureObjectMapper();
        customize(builder, customizers);
        return builder;
    }

    private void customize(Jackson2ObjectMapperBuilder builder,
                           List<Jackson2ObjectMapperBuilderCustomizer> customizers) {
        for (Jackson2ObjectMapperBuilderCustomizer customizer : customizers) {
            customizer.customize(builder);
        }
    }

    private Jackson2ObjectMapperBuilder configureObjectMapper() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        List<String> activeProfiles = asList(env.getActiveProfiles());
        if (activeProfiles.contains(SPRING_PROFILE_DEVELOPMENT)) {
            builder.featuresToEnable(SerializationFeature.INDENT_OUTPUT);
        }
        return builder;
    }
}

To provide some context, this class sits in my own spring starter project for REST services that just auto configures a number of things, like ControllerAdvice and some trivial features like the above.

So my goal is to extend the Jackson configuration rather than to override any configuration provided by boot or other packages.

Fachanan answered 1/9, 2016 at 5:47 Comment(0)
D
34

To customize the Jackson ObjectMapper that's already pre-configured by Spring Boot, I was able to do this (the example here is to add a custom deserializer).

Configuration class:

@SpringBootConfiguration
public class Application {

    @Autowired
    private BigDecimalDeserializer bigDecimalDeserializer;

    ...

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer addCustomBigDecimalDeserialization() {
        return new Jackson2ObjectMapperBuilderCustomizer() {

            @Override
            public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
                jacksonObjectMapperBuilder.deserializerByType(BigDecimal.class, bigDecimalDeserializer);
            }

        };
    }

    ...

}

And my custom deserializer, to show how it's picked up by Spring:

@Component
public class BigDecimalDeserializer extends StdDeserializer<BigDecimal> {

    public BigDecimalDeserializer() {
        super(BigDecimal.class);
    }

    @Override
    public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        ...
    }

    ...

}
Dunseath answered 14/10, 2016 at 19:54 Comment(1)
Spot on! This is what I originally attemped to do, but must have been doing something wrong, thanks.Fachanan
S
9

It depends on what you're trying to do.

If you want to make some customisations in addition to those that are performed by default then you should create your own Jackson2ObjectMapperBuilderCustomizer implementation and expose it as a bean. What you currently have is a more complex version of this. Rather than having the customisers injected and then calling them yourself, you can just create your own customiser bean and Boot will call it for you.

If you want to take complete control and switch off all of Boot's customisations then create a Jackson2ObjectMapperBuilder or ObjectMapper bean and configure it as required. The builder approach is preferred as this builder is then also used to configure ObjectMappers created by other components such as Spring Data REST.

Looking at your code and taking a step back, you could configure things far more simply by using a profile-specific configuration file (something like application-dev.properties) to enable indenting of Jackson's output. You can read more about that here.

Sherburn answered 1/9, 2016 at 7:51 Comment(1)
Thanks that is what I originally had done, but it seemed to have no effect. I'll post the code I had tomorrow and maybe you can tell where I wen't wrong. As for your suggestion to configure this via the properties file, I've updated my question to provide a bit more context into how I am using this configuration class.Fachanan
N
0

just create an ObjectMapper bean:

@Bean
ObjectMapper objectMapper() {
    return Jackson2ObjectMapperBuilder
            .json()
            .featuresToEnable(MapperFeature.DEFAULT_VIEW_INCLUSION)
            .build();
}
Niko answered 1/9, 2016 at 6:13 Comment(2)
Sorry I probably could have made it more clear that I was essentially looking to extend the object mapper features. Whereas your suggestion would in effect override any ObjectMapper beans, such as the default one spring boot configuresFachanan
It's not vey good approach for spring boot as there can be multiple jackson customizers and returning built instance of object mapper makes them completely useless.Powel

© 2022 - 2024 — McMap. All rights reserved.