¿Cómo personalizar el mapeador Jackson JSON utilizado implícitamente por Spring Boot?

Estoy usando Spring Boot (1.2.1), de una manera similar a la de su tutorial de creación de un servicio web RESTful :

@RestController public class EventController { @RequestMapping("/events/all") EventList events() { return proxyService.getAllEvents(); } } 

Así que arriba, Spring MVC utiliza implícitamente Jackson para serializar mi objeto EventList en JSON.

Pero quiero hacer algunas personalizaciones simples para el formato JSON, tales como:

 setSerializationInclusion(JsonInclude.Include.NON_NULL) 

La pregunta es, ¿cuál es la forma más sencilla de personalizar el mapeador JSON implícito?

Probé el enfoque en esta publicación de blog , creando un CustomObjectMapper, y así sucesivamente, pero el paso 3, “Registrar clases en el contexto Spring”, falla:

 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jacksonFix': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.acme.project.JacksonFix.setAnnotationMethodHandlerAdapter(org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} 

Parece que esas instrucciones son para versiones anteriores de Spring MVC, mientras que estoy buscando una forma simple de hacerlo funcionar con la última versión de Spring Boot.

Si está utilizando Spring Boot 1.3, puede configurar la inclusión de serialización a través de application.properties :

 spring.jackson.serialization-inclusion=non_null 

Después de los cambios en Jackson 2.7, Spring Boot 1.4 usa una propiedad llamada spring.jackson.default-property-inclusion en spring.jackson.default-property-inclusion lugar:

 spring.jackson.default-property-inclusion=non_null 

Consulte la sección ” Personalizar el ObjectMapper Jackson ” en la documentación de Spring Boot.

Si está utilizando una versión anterior de Spring Boot, la forma más fácil de configurar la inclusión de serialización en Spring Boot es declarar su propio bean Jackson2ObjectMapperBuilder debidamente configurado. Por ejemplo:

 @Bean public Jackson2ObjectMapperBuilder objectMapperBuilder() { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.serializationInclusion(JsonInclude.Include.NON_NULL); return builder; } 

Estoy respondiendo algo tarde a esta pregunta, pero a alguien, en el futuro, podría resultarle útil. El siguiente enfoque, además de muchos otros enfoques, funciona mejor, y personalmente creo que sería más adecuado para una aplicación web.

 @Configuration @EnableWebMvc public class WebConfiguration extends WebMvcConfigurerAdapter { ... other configurations @Override public void configureMessageConverters(List> converters) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.serializationInclusion(JsonInclude.Include.NON_NULL); builder.propertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); builder.serializationInclusion(Include.NON_EMPTY); builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd")); converters.add(new MappingJackson2HttpMessageConverter(builder.build())); converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); } } 

Se pueden configurar muchas cosas en propertiesproperties. Lamentablemente, esta característica solo se encuentra en la Versión 1.3, pero puede agregarla en una clase de configuración

 @Autowired(required = true) public void configeJackson(ObjectMapper jackson2ObjectMapper) { jackson2ObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); } 

[ACTUALIZACIÓN: debe trabajar en ObjectMapper porque se llama a build() -method antes de que se ejecute la configuración.]

La documentación indica varias formas de hacer esto.

Si desea reemplazar completamente el ObjectMapper defecto, defina un @Bean de ese tipo y @Primary como @Primary .

La definición de un @Bean de tipo Jackson2ObjectMapperBuilder le permitirá personalizar tanto ObjectMapper como XmlMapper predeterminados (utilizados en MappingJackson2HttpMessageConverter y MappingJackson2XmlHttpMessageConverter respectivamente).

spring.jackson.serialization-inclusion=non_null solía funcionar para nosotros

Pero cuando actualizamos la versión de arranque de spring a 1.4.2.RELEASE o superior, dejó de funcionar.

Ahora, otra propiedad spring.jackson.default-property-inclusion=non_null está haciendo la magia.

de hecho, la serialization-inclusion está en desuso. Esto es lo que mi intellij me arroja.

Obsoleto: ObjectMapper.setSerializationInclusion quedó en desuso en Jackson 2.7

Entonces, comienza a usar spring.jackson.default-property-inclusion=non_null en spring.jackson.default-property-inclusion=non_null lugar

Me encontré con otra solución, que es bastante agradable.

Básicamente, solo haga el paso 2 del blog publicado mencionado , y defina un ObjectMapper personalizado como Spring @Component . (Las cosas comenzaron a funcionar cuando eliminé todas las cosas de AnnotationMethodHandlerAdapter del paso 3)

 @Component @Primary public class CustomObjectMapper extends ObjectMapper { public CustomObjectMapper() { setSerializationInclusion(JsonInclude.Include.NON_NULL); configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } } 

Funciona siempre que el componente esté en un paquete escaneado por Spring. (Usar @Primary no es obligatorio en mi caso, pero ¿por qué no hacer las cosas explícitamente?)

Para mí, hay dos beneficios en comparación con el otro enfoque:

  • Esto es más simple; Puedo extender una clase de Jackson y no necesito saber mucho sobre cosas específicas de Spring como Jackson2ObjectMapperBuilder .
  • Quiero usar las mismas configuraciones de Jackson para deserializar JSON en otra parte de mi aplicación, y de esta manera es muy simple: new CustomObjectMapper() lugar de new ObjectMapper() .

Encontré la solución descrita anteriormente con:

spring.jackson.serialization-inclusion = non_null

Solo funciona desde la versión 1.4.0.RELEASE del arranque de spring. En todos los demás casos, la configuración se ignora.

Lo verifiqué experimentando con una modificación de la muestra de bota de muelles “spring-boot-sample-jersey”

Conozco la pregunta sobre cómo arrancar Spring, pero creo que mucha gente está buscando cómo hacerlo en el arranque sin Spring, como yo, buscando casi todo el día.

Por encima de Spring 4, no es necesario configurar MappingJacksonHttpMessageConverter si solo tiene la intención de configurar ObjectMapper .

Solo tienes que hacer:

 public class MyObjectMapper extends ObjectMapper { private static final long serialVersionUID = 4219938065516862637L; public MyObjectMapper() { super(); enable(SerializationFeature.INDENT_OUTPUT); } } 

Y en su configuración de Spring, cree este bean:

 @Bean public MyObjectMapper myObjectMapper() { return new MyObjectMapper(); }