web-dev-qa-db-fra.com

Désérialisation de LocalDateTime avec le module Jackson JSR310

J'utilise la bibliothèque décrite la page Jackson Datatype JSR310 mais j'ai toujours du mal à la faire fonctionner.

J'ai configuré le haricot suivant:

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

Lorsque j'appelle mon API REST, le format de date généré est yyyy-MM-dd'T'HH:ss.SSSSSS, par exemple. 2015-04-11T00:10:38.905847. Ceci est parfaitement géré par mon code AngularJS.

Lorsque je souhaite soumettre quelque chose à l'API REST, la date est publiée sous la forme yyyy-MM-dd'T'HH:mm:ss.SSS'Z', par exemple. 2015-04-09T08:30:00.000Z

Jackson continue à se plaindre du "Z" à la fin. Si je regarde la LocalDateTimeDeserializer dans la documentation, il utilise le DateTimeFormatter.ISO_LOCAL_DATE_TIME qui se résume en ISO_LOCAL_DATE'T'ISO_LOCAL_TIME et il mentionne qu'il n'a pas de zone de substitution.

J'ai donc pensé que je devrais définir la DateFormat sur la ObjectMapper que je crée:

@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;
}

Mais cela ne fait rien. Je l'ai changé pour quelque chose de simple comme yyyy-MM-dd mais la date sérialisée est restée dans le format précédent et la désérialisation n'est pas affectée non plus.

Qu'est-ce que je fais mal ici pour que cela fonctionne? Le format de date dans mon code JavaScript est, à ma connaissance, le format ISO 8601 ...

14
Mekswoll

Il n'est pas nécessaire d'écrire votre propre sérialiseur. Il suffit d’utiliser celui par défaut, mais en créant une instance avec un autre format (le time_zone) pour que la partie en excès soit simplement coupée:

new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME)

Dans mon cas, j'ai une contextResolver comme celle-ci à réaliser au niveau de la configuration:

@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;
    }  
}
22
user1299153

Pour l'instant, LocalDateTimeDeserializer ne semble pas respecter le format de date défini pour le mappeur d'objets.

Pour que cela fonctionne, vous pouvez remplacer LocalDateTimeDeserializer ou utiliser ZoneDateTime qui gère le caractère 'Z' à la fin.

Voici un exemple:

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));
    }
}

Sortie:

"2015-04-11T18:24:47.815Z"
2015-04-11T18:24:47.815Z[GMT]
5
Alexey Gavrilov

Hibernate 4, Spring 4 - REST WS, Client - Spring Boot 1.5.2. Dans mon cas, j'ai utilisé dans la classe Entity ZonedDateTime pour mapper Timestamp dans la base de données. Hibernate et Spring Boot REST fonctionnent correctement. Je dois seulement ajouter des bibliothèques dans le fichier pom:

    <!-- 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>

Donc, je suppose que ce convertisseur est également implémenté dans Spring pour LocalDateTime. Le jackson.version est le dernier.

1
hariprasad