Saltar al contenido

Serializar Java8 LocalDateTime a la marca de tiempo UTC usando Jackson

Después de tanto batallar hemos encontrado la respuesta de esta escollo que algunos los lectores de nuestro sitio han presentado. Si tienes algo que compartir no dejes de compartir tu información.

Solución:

Puede personalizar un serializador y un deserializador para LocalDateTime, por ejemplo:

CustomLocalDateTimeSerializer

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class CustomLocalDateTimeSerializer extends StdSerializer 

    protected CustomLocalDateTimeSerializer(Class t) 
        super(t);
    

    protected CustomLocalDateTimeSerializer() 
        this(null);
    

    @Override
    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider sp)
            throws IOException 
        Long epoch = value.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
        gen.writeString(epoch.toString());
    

CustomLocalDateTimeDesSerializer:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

class CustomLocalDateTimeDesSerializer extends StdDeserializer 

    protected CustomLocalDateTimeDesSerializer() 
        this(null);
    

    protected CustomLocalDateTimeDesSerializer(Class t) 
        super(t);
    

    @Override
    public LocalDateTime deserialize(JsonParser jsonparser, DeserializationContext context)
            throws IOException 
        Long timestamp = Long.parseLong(jsonparser.getText());
        return LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault());
    

Y utilícelos:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.time.LocalDateTime;

public class RestObject 

    private LocalDateTime timestamp = LocalDateTime.now();

    @JsonSerialize(using = CustomLocalDateTimeSerializer.class)
    @JsonDeserialize(using = CustomLocalDateTimeDesSerializer.class)
    public LocalDateTime getTimestamp() 
        return timestamp;
    

    public static void main(String[] args) throws Exception 
        ObjectMapper objectMapper = new ObjectMapper();
        // "timestamp":"1549026058"
        System.out.println(objectMapper.writeValueAsString(new RestObject()));
    

La siguiente solución resuelve la tarea de serializar / deserializar el LocalDateTime a la marca de tiempo y relevante al menos para spring-boot v1.5 y también incluye los siguientes puntos que no se tienen en cuenta en la respuesta de @ xingbin:

  • Si existe la necesidad de tener el mismo comportamiento que para java.util.Date tengo que usar el toInstant().toEpochMilli() en cambio el toInstant().getEpochSecond()
  • Comprobar en null el valor de deserializar
  • Y punto opcional: especifique esta configuración de serialización / deserialización para Jackson ObjectMapper

La clase de serializador de marca de tiempo:

public class LocalDateTimeSerializer extends StdSerializer 
    private static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("UTC");

    public LocalDateTimeSerializer() 
        super(LocalDateTime.class);

    

    @Override
    public void serialize(final LocalDateTime value,
                          final JsonGenerator generator,
                          final SerializerProvider provider) throws IOException 
        if (value != null) 
            final long mills = value.atZone(DEFAULT_ZONE_ID).toInstant().toEpochMilli();
            generator.writeNumber(mills);
         else 
            generator.writeNull();
        
    

La clase de deserializador de marca de tiempo:

public class LocalDateTimeDeserializer extends StdDeserializer 
    private static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("UTC");

    public LocalDateTimeDeserializer() 
        super(LocalDateTime.class);
    

    @Override
    public LocalDateTime deserialize(final JsonParser parser,
                                     final DeserializationContext context) throws IOException 
        final long value = parser.getValueAsLong();
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(value), DEFAULT_ZONE_ID);
    

los mapeador de objetos configuración:

@Configuration
public class ObjectMapperConfiguration 
    @Bean
    public ObjectMapper objectMapper() 
        final ObjectMapper objectMapper = new ObjectMapper();
        final SimpleModule module = new SimpleModule();
        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
        objectMapper.registerModule(module);
        return objectMapper;
    

Comentarios y calificaciones

Tienes la posibilidad dar difusión a esta sección si te fue de ayuda.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *