2015-04-10 29 views
10

Sto utilizzando la libreria descritta the Jackson Datatype JSR310 page ma ho ancora difficoltà a farlo funzionare.Deserializzazione di LocalDateTime con il modulo Jackson JSR310

Ho configurato il seguente fagiolo:

@Bean 
@Primary 
public ObjectMapper objectMapper() { 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.registerModule(new JSR310Module()); 
    return mapper; 
} 

Quando chiamo il mio API REST l'output formato della data è yyyy-MM-dd'T'HH:ss.SSSSSS, per esempio 2015-04-11T00:10:38.905847. Questo viene gestito dal mio codice AngularJS bene.

Quando si desidera inviare qualcosa all'API REST, la data viene indicata come yyyy-MM-dd'T'HH:mm:ss.SSS'Z', ad es. 2015-04-09T08:30:00.000Z

Jackson continua a lamentarsi della "Z" alla fine. Se guardo lo LocalDateTimeDeserializer nella documentazione utilizza lo DateTimeFormatter.ISO_LOCAL_DATE_TIME che si riduce a ISO_LOCAL_DATE'T'ISO_LOCAL_TIME e indica che non ha alcuna zona di sostituzione.

quindi ho pensato che avrei dovuto impostare il DateFormat sul ObjectMapper Sto creando:

@Bean 
@Primary 
public ObjectMapper objectMapper() { 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.registerModule(new JSR310Module()); 
    mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")); 
    return mapper; 
} 

Ma questo non fa nulla. L'ho modificato in qualcosa di semplice come yyyy-MM-dd ma la data serializzata è rimasta nel formato precedente e anche la deserializzazione non è stata modificata.

Cosa sto facendo di sbagliato qui per farlo funzionare? Il formato della data nel mio codice JavaScript è, per quanto ne so il formato ISO 8601 ...

+2

Penso che potrebbe funzionare se si passa a ZoneDateTime. –

+0

@AlexeyGavrilov, che funziona davvero, grazie. Se lo invii come risposta, lo contrassegnerò come corretto. Ancora strano che l'impostazione di dateFormat sullo stesso objectmapper non abbia assolutamente alcun effetto per quanto riguarda la serializzazione/deserializzazione ma usare ZonedDateTime è abbastanza semplice :-) – Mekswoll

+1

Il DateFormat di ObjectMapper è solo per il supporto java.util.Date integrato, I indovina. Passare un valore con un'indicazione del fuso orario a un LocalDateTime è un odore- Istantaneo o OffsetDateTime (o anche ZonedDateTime) è più applicabile. – araqnid

risposta

18

Non è necessario scrivere il proprio serializzatore. E 'sufficiente utilizzare quella di default, ma fare un'istanza con un altro formato (la time_zone uno) in modo che la parte superiore è appena tagliato:

new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME) 

Nel mio caso ho ottenuto un contextResolver come questo per ottenere in sede di configurazione livello:

@Service 
@Provider 
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> { 
    private final ObjectMapper mapper; 

    public ObjectMapperContextResolver() { 
     mapper = new ObjectMapper(); 
     JavaTimeModule javaTimeModule=new JavaTimeModule(); 
     // Hack time module to allow 'Z' at the end of string (i.e. javascript json's) 
     javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME)); 
     mapper.registerModule(javaTimeModule); 
     mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 
    } 

    @Override 
    public ObjectMapper getContext(Class<?> type) { 
     return mapper; 
    } 
} 
+1

Credo che questa risposta sia più appropriata poiché dimostra come configurare l'ObjectMapper per gestire automaticamente e correttamente la deserializzazione. Questo è necessario se non si utilizza manualmente l'intsance 'ObjectMapper' per leggere le stringhe in entrata, ma si lavora invece su cose come' RestTemplate' – demaniak

+0

Hmmm. Ottengo questa eccezione quando ho provato questo: java.lang.IllegalAccessError: provato ad accedere al metodo com.fasterxml.jackson.databind.ser.std.StdSerializer. <init> ( Ljava/lang/Classe ; ) V dalla classe com.fasterxml.jackson.datatype.jsr310.JavaTimeModule – rakehell

+0

si potrebbe dare un'occhiata https://stackoverflow.com/questions/44918021/how-to-use-some -jackson-deserializer-in-own-custom-deserializer? È simile? Se possibile, rispondi per favore. –

5

Per ora LocalDateTimeDeserializer non sembra rispettare il formato data impostato per il mappatore oggetto.

Per farlo funzionare, è possibile ignorare LocalDateTimeDeserializer o passare a utilizzare ZoneDateTime che gestisce il carattere "Z" alla fine.

Ecco un esempio:

public class Java8DateFormat { 
    public static void main(String[] args) throws IOException { 
     final ObjectMapper mapper = new ObjectMapper(); 
     mapper.registerModule(new JSR310Module()); 
     // mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")); 

     final String date = mapper.writeValueAsString(new Date()); 
     System.out.println(date); 
     System.out.println(mapper.readValue(date, ZonedDateTime.class)); 
    } 
} 

uscita:

"2015-04-11T18:24:47.815Z" 
2015-04-11T18:24:47.815Z[GMT] 
+3

Si noti che 'JSR310Module' è stato deprecato, usare invece' JavaTimeModule'. – demaniak

1

Hibernate 4, Primavera 4 - RIPOSO WS, client - Primavera Boot 1.5.2. Nel mio caso l'ho utilizzato nell'entità ZonedDateTime class per mappare Timestamp nel database. Hibernate e Spring Boot REST funzionano bene. Devo solo aggiungere librerie in pom di file:

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations --> 
    <dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-annotations</artifactId> 
     <version>${jackson.version}</version> 
    </dependency> 

    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310 --> 
    <dependency> 
     <groupId>com.fasterxml.jackson.datatype</groupId> 
     <artifactId>jackson-datatype-jsr310</artifactId> 
     <version>${jackson.version}</version> 
    </dependency> 

quindi suppongo, che convertitore è implementato all'interno della sorgente a LocalDateTime come well.The jackson.version è quello più recente.

+0

L'OP ha affermato che sta già utilizzando il modulo Jackson JSR 310 (altrimenti la classe 'JSR310Module' non sarebbe disponibile). –

+0

Sì, certo, ma non ho fatto altro. Object Mapper non è necessario, né modulo di registrazione. – hariprasad

Problemi correlati