Al usar el formato JSON, Spring Boot usará una instancia de ObjectMapper para serializar las respuestas y deserializar las requests. En este artículo, veremos las formas más comunes de configurar las opciones de serialización y deserialización.
Veamos la configuración predeterminada. Entonces, por defecto, la configuración de Spring Boot será la siguiente:
- Deshabilitar MapperFeature.DEFAULT_VIEW_INCLUSION
- Deshabilite la característica de deserialización. FALLO_EN_PROPIEDADES_DESCONOCIDAS
- Deshabilite la característica de serialización. ESCRIBIR_FECHAS_AS_TIMESTAMPS
Comencemos con un ejemplo más rápido implementando el mismo
Implementación:
- El cliente envía una solicitud GET a nuestro/coffee?name=Lavazza
- El controlador devolverá un nuevo objeto Café.
- Spring usará opciones de personalización mediante el uso de objetos String y LocalDateTime
Es el siguiente, por lo que principalmente necesitamos crear una clase llamada Coffee, que es la siguiente:
// Class public class Coffee { // Getters and setters private String name; private String brand; private LocalDateTime date; }
- Ahora también definiremos un controlador REST simple para demostrar la serialización:
@GetMapping ("/coffee") public Coffee getCoffee( @RequestParam(required = false) String brand, @RequiredParam(required = false) String name) { return new Coffee() .setBrand(brand) .setDate(FIXED_DATE) .setName(name); }
- Por defecto, la respuesta al llamar a GET http://localhost:8080/coffee? brand =lavazza será la siguiente :
{ "name": null, "brand": Lavazza", "date": "2020 - 11 - 16T10: 21: 35.974" }
- Ahora nos gustaría excluir valores nulos y tener un formato de fecha personalizado (dd-MM-yyy HH:mm) . La respuesta final será la siguiente:
{ "brand:" "Lavazza", "date": "04-11-20202 10:34" }
- Cuando usamos Spring Boot, tenemos la opción de personalizar el ObjectMapper predeterminado o anularlo. Cubriremos ambas opciones en las siguientes secciones.
Ahora pasemos al punto excéntrico del artículo personalizando el asignador de objetos predeterminado. Aquí. discutiremos cómo personalizar el ObjectMapper predeterminado que usa Spring Boot.
Propiedades de la aplicación y módulo Jackson personalizado
La forma más sencilla de configurar el mapeador es a través de las propiedades de la aplicación. La estructura general de la configuración es la siguiente:
spring.jackson.<category_name>.<feature_name>=true, false
Como ejemplo, si queremos deshabilitar SerializationFeature. WRITE_DATES_AS_TIMESTAMPS, agregaremos:
spring.jackson.serialization.write-dates-as-timestamps=false
Además de las categorías de características mencionadas, también podemos configurar la inclusión de propiedades:
spring.jackson.default-property-inclusion=always, non_null, non_absent, non_default, non_empty
Configuración de las variables de entorno en el enfoque más simple. La desventaja de este enfoque es que no podemos personalizar las opciones avanzadas, como tener un formato de fecha personalizado para LocalDateTime. En este punto, obtendremos el resultado que se muestra a continuación:
{ "brand": "Lavazza", "date": "2020-11-16T10:35:34.593" }
Ahora, para lograr nuestro objetivo, registraremos un nuevo JavaTimeModule con nuestro formato de fecha personalizado:
@Configuration @PropertySource("classpath:coffee.properties") // Class public class CoffeeRegisterModuleConfig { @Bean public Module javaTimeModule() { JavaTimeModule module = new JavaTimeModule(); module.addSerializer(LOCAL_DATETIME_SERIALIZER); return module; } }
Jackson2ObjectMapperBuilderPersonalizador
El propósito de esta interfaz funcional es permitirnos crear beans de configuración. Se aplicarán al ObjectMapper predeterminado creado a través de Jackson2ObjectMapperBuilder.
@Bean public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL) .serializers(LOCAL_DATETIME_SERIALIZER); }
Los beans de configuración se aplican en un orden específico, que podemos controlar usando las anotaciones @Order. Este enfoque elegante es adecuado si queremos configurar ObjectMapper desde diferentes configuraciones o módulos.
Jackson2ObjectMapperBuilder
Otro enfoque limpio es definir un bean Jackson2ObjectMapperBuilder. En realidad, Spring Boot usa este constructor de manera predeterminada al construir el ObjectMapper y automáticamente recogerá el definido:
@Bean public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { return new Jackson2ObjectMapperBuilder().serializers(LOCAL_DATETIME_SERIALIZER) .serializationInclusion(JsonInclude.Include.NON_NULL); }
Configurará dos opciones por defecto:
- Deshabilitar MapperFeature.DEFAULT_VIEW_INCLUSION
- Deshabilitar DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
Según la documentación de Jackson2ObjectMapperBuilder, también registrará algunos módulos si están presentes en el classpath:
- jackson-datatype-jdk8: soporte para otros tipos de Java 8 como Opcional
- jackson-datatype-jsr310: soporte para tipos de API de fecha y hora de Java 8
- jackson-datatype-joda: soporte para tipos Joda-Time
- jackson-module-kotlin: soporte para clases de Kotlin y clases de datos
Nota: La ventaja de este enfoque es que Jackson2ObjectMapperBuilder ofrece una manera simple e intuitiva de construir un ObjectMapper.
Simplemente podemos definir un bean con el tipo MappingJackson2HttpMessageConverter, y Spring Boot lo usará automáticamente:
@Bean // Convertor method public MappingJackson2HttpMessageConverter() { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder().serializers(LOCAL_DATE_SERIALIZER) .serializationInclusion(JsonInclude.Include.NON_NULL); return new MappingJackson2HttpMessageConverter(builder.build()); }
Nota: asegúrese de consultar nuestro artículo Spring Http Message Converters para obtener más información.
Prueba de la configuración
Por último, para probar nuestra configuración, usaremos TestRestTemplate y serializaremos los objetos como String. De esta forma, podemos validar que nuestro objeto Coffee esté serializado sin valores nulos y con el formato de fecha personalizado:
@Test public void whenGetCoffee_thenSerializedWithDateAndNonNull() { String formattedDate = DateTimeFormatter.ofPattern(CoffeeConstants.dateTimeFormat).format(FIXED_DATE); // Our strings String brand = "Lavazza"; String url = "/coffee?branf=" + brand; String response = restTemplate.getForObject(url, String.class); assertThat(response).isEqualTo("{"brand\":\"" + brand + "\",\"date\":\"" + formatedDate + "\"}"); }
Conclusión: Echamos un vistazo a varios métodos para configurar las opciones de serialización de JSON al usar Spring Boot. Aquí vimos dos enfoques diferentes: configurar las opciones predeterminadas o anular la configuración predeterminada.
Publicación traducida automáticamente
Artículo escrito por akashpandit1103 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA