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