Configure Jackson to omit lazy-loading attributes in Spring Boot

二次信任 提交于 2019-11-27 07:54:15

With recent versions of Spring Boot this is much easier.

Any beans of type com.fasterxml.jackson.databind.Module will be automatically registered with the auto-configured Jackson2ObjectMapperBuilder and applied to any ObjectMapper instances that it creates. This provides a global mechanism for contributing custom modules when you add new features to your application.

74.3 Customize the Jackson ObjectMapper

First ensure you have the required Jackson dependency:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-hibernate4</artifactId>
</dependency>

You can then just include the module as a @Bean in the application context.

@Bean
public Module hibernate4Module()
{
    return new Hibernate4Module();
}

If you are using SpringBoot, ideally you should already have Hibernate4Module. Else add this dependency

    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-hibernate4</artifactId>
        <version>2.5.3</version>
    </dependency>

Next create a class called "HibernateAwareObjectMapper" or whatever you want to name it:

with following contents:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;

    public class HibernateAwareObjectMapper extends ObjectMapper {

        public HibernateAwareObjectMapper() {
            registerModule(new Hibernate4Module());
        }
    }

for different versions of Hibernate, refer to these Hibernate modules:

// for Hibernate 4.x:
mapper.registerModule(new Hibernate4Module());
// or, for Hibernate 5.x
mapper.registerModule(new Hibernate5Module());
// or, for Hibernate 3.6
mapper.registerModule(new Hibernate3Module());

Now you need to register your HibernateAwareObjectMapper through a message Converter. For this create a Config class that extens extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter. (If you already have one just follow the next step).

Now register the MessageConverter using HibernateObjectMapper :

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters){
    List<MediaType> supportedMediaTypes=new ArrayList<>();
    supportedMediaTypes.add(MediaType.APPLICATION_JSON);
    supportedMediaTypes.add(MediaType.TEXT_PLAIN);
    MappingJackson2HttpMessageConverter converter=new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(new HibernateAwareObjectMapper());
    converter.setPrettyPrint(true);
    converter.setSupportedMediaTypes(supportedMediaTypes);
    converters.add(converter);
    super.configureMessageConverters(converters);
}

Viola !!! That should be enough. This is the pure-java (no-xml) way of doing this for a spring boot web app.

Feel free to comment if you want to add to Answer.

yeye

I user springboot and hibernamte5.0.x. It works!

1. pom.xml

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-hibernate5</artifactId>
    <version>2.8.4</version>
</dependency>

2. Webconfig

@Configuration
public class WebConfig implements WebMvcConfigurer {

    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter converter : converters) {
            if (converter instanceof org.springframework.http.converter.json.MappingJackson2HttpMessageConverter) {
                ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
                mapper.registerModule(new Hibernate5Module());
                // replace Hibernate4Module() with the proper class for your hibernate version.
            }
        }
    }
}

For me the easiest way to achieve this was to extend WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter and override extendMessageConverters method. Inside I've searched for the MappingJackson2HttpMessageConverter and just registered Jackson Hibernate module.

@Configuration
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class CustomWebMvcAutoConfig extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter
{
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter converter : converters) {
            if (converter instanceof org.springframework.http.converter.json.MappingJackson2HttpMessageConverter) {
                ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
                mapper.registerModule(new Hibernate4Module());
                // replace Hibernate4Module() with the proper class for your hibernate version.
            }
        }
    }
}

This way you won't lose all the default converters configured by Spring.

@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = jsonConverter.getObjectMapper();
    objectMapper.registerModule(new Hibernate5Module());


    return jsonConverter;
}

What @Grzegorz wrote is perfect for me. Just to present here the his solution without his custom classes:

edit: i'm in RestController domain

@Configuration
public class CustomWebMvcAutoConfig extends WebMvcConfigurerAdapter
{
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter converter : converters) {
            if (converter instanceof org.springframework.http.converter.json.MappingJackson2HttpMessageConverter) {
                ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
                mapper.registerModule(new Hibernate5Module());
                // replace Hibernate4Module() with the proper class for your hibernate version.
            }
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!