util serialize localdatetime jsonformat instant java json spring-boot jackson zoneddatetime

java - serialize - localdatetime spring boot



Jackson serializa un ZonedDateTime incorrectamente en Spring Boot (3)

Hay una biblioteca jackson-datatype-jsr310 . Intentalo.

Esta biblioteca cubre la nueva API de datetime e incluye serializadores para ZonedDateTime también.

Todo lo que necesitas es solo agregar JavaTimeModule :

ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule());

ACTUALIZAR

Para convertir datetime en ISO-8601 cadena ISO-8601 , debe deshabilitar la función WRITE_DATES_AS_TIMESTAMPS . Puede hacerlo fácilmente anulando el bean ObjectMapper o usando las propiedades de la aplicación :

spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false

Tengo una aplicación sencilla con Spring Boot y Jetty. Tengo un controlador simple que devuelve un objeto que tiene un ZonedDateTime de Java 8:

public class Device { // ... private ZonedDateTime lastUpdated; public Device(String id, ZonedDateTime lastUpdated, int course, double latitude, double longitude) { // ... this.lastUpdated = lastUpdated; // ... } public ZonedDateTime getLastUpdated() { return lastUpdated; } }

En mi RestController simplemente tengo:

@RequestMapping("/devices/") public @ResponseBody List<Device> index() { List<Device> devices = new ArrayList<>(); devices.add(new Device("321421521", ZonedDateTime.now(), 0, 39.89011333, 24.438176666)); return devices; }

Esperaba que ZonedDateTime se formatee de acuerdo con el formato ISO, pero en cambio, estoy obteniendo un volcado JSON completo de la clase como esta:

"lastUpdated":{"offset":{"totalSeconds":7200,"id":"+02:00","rules":{"fixedOffset":true,"transitionRules":[],"transitions":[]}},"zone":{"id":"Europe/Berlin","rules":{"fixedOffset":false,"transitionRules":[{"month":"MARCH","timeDefinition":"UTC","standardOffset":{"totalSeconds":3600,"id":"+01:00","rules":{"fixedOffset":true,"transitionRules":[],"transitions":[]}},"offsetBefore":{"totalSeconds":3600,"id":"+01:00","rules":{"fixedOffset":true,"transitionRules":[],"transitions":[]}},"offsetAfter":{"totalSeconds":7200,"id":"+02:00", ...

Solo tengo una aplicación spring-boot-starter-web spring-boot-starter-jetty , usando spring-boot-starter-jetty y excluyendo spring-boot-starter-tomcat .

¿Por qué Jackson se está comportando así en Spring Boot?

** ACTUALIZACIÓN **

Para aquellos que buscan una guía paso a paso completa sobre cómo resolver esto, encontré esto después de hacer la pregunta: http://lewandowski.io/2016/02/formatting-java-time-with-spring-boot-using-json/


La respuesta ya se mencionó anteriormente, pero creo que falta información. Para aquellos que buscan analizar las marcas de tiempo de Java 8 en muchas formas (no solo ZonedDateTime). Necesita una versión reciente de jackson-datatype-jsr310 en su POM y tiene el siguiente módulo registrado:

ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

Para probar este código

@Test void testSeliarization() throws IOException { String expectedJson = "{/"parseDate/":/"2018-12-04T18:47:38.927Z/"}"; MyPojo pojo = new MyPojo(ZonedDateTime.parse("2018-12-04T18:47:38.927Z")); // serialization assertThat(objectMapper.writeValueAsString(pojo)).isEqualTo(expectedJson); // deserialization assertThat(objectMapper.readValue(expectedJson, MyPojo.class)).isEqualTo(pojo); }

Tenga en cuenta que puede configurar su asignador de objetos globalmente en Spring o dropwizard para lograr esto. Todavía no he encontrado una forma limpia de hacer esto como una anotación en un campo sin registrar un serializador (des) personalizado.


Si no confía en la función de configuración automática de SpringBoot (no proporciona spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false propiedad spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false en su archivo de configuración) o por cualquier motivo, cree la instancia de ObjectMapper manualmente. Puede desactivar esta función programáticamente de la siguiente manera:

ObjectMapper m = new ObjectMapper(); m.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

esto es para jackson 2.8.7