Description du problème
Lors de la sérialisation et de la désérialisation d'une collection contenant des objets LocalDateTime, vous pouvez rencontrer l'exception suivante :
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Java 8 date/time type `java.time.LocalDate` not supported by default: add Module
"com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: java.util.HashMap["data"])
En effet, la bibliothèque Jackson ne prend pas en charge la sérialisation et la désérialisation du type LocalDateTime par défaut. Pour résoudre ce problème, nous devons personnaliser le comportement de la sérialisation et de la désérialisation.
Première solution
1. Introduire des dépendances
<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${
jackson.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
2. Définir le module horaire
ObjectMapper objectMapper = new CustomObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
objectMapper.registerModule(new JavaTimeModule());
Map<String, Object> map = new HashMap<>();
map.put("time", LocalDateTime.now());
map.put("data", LocalDate.now());
objectMapper.writeValueAsString(map);
Solution 2
1. Sérialiseur personnalisé
Tout d’abord, nous devons créer un sérialiseur personnalisé pour gérer la sérialisation et la désérialisation du type LocalDateTime. La mise en œuvre spécifique est la suivante :
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.time.LocalDateTime;
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(value.toString());
}
}
Dans ce sérialiseur personnalisé, nous convertissons l'objet LocalDateTime en chaîne, puis utilisons gen.writeString()
la méthode pour l'écrire dans le flux de sortie JSON.
Ensuite, nous devons appliquer ce sérialiseur personnalisé à notre classe d'entité. Supposons que nous ayons une Event
classe d'entité nommée qui contient une propriété de type LocalDateTime eventTime
:
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.time.LocalDateTime;
public class Event {
private String name;
private LocalDateTime eventTime;
// getter and setter methods ...
@JsonSerialize(using = LocalDateTimeSerializer.class)
public LocalDateTime getEventTime() {
return eventTime;
}
public void setEventTime(LocalDateTime eventTime) {
this.eventTime = eventTime;
}
}
En getEventTime()
ajoutant @JsonSerialize
une annotation sur la méthode et en spécifiant le sérialiseur personnalisé que nous venons de créer ( ), nous pouvons garantir que le sérialiseur personnalisé que nous avons défini est utilisé lors Using = LocalDateTimeSerializer.class
de la sérialisation et de la désérialisation des propriétés.eventTime
2. Désérialiseur personnalisé (facultatif)
Si nous souhaitons conserver les informations de type d'un objet LocalDateTime lors de la désérialisation, nous pouvons créer un désérialiseur personnalisé. La mise en œuvre spécifique est la suivante :
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
private static final LocalDateTime minValue = LocalDateTime.MIN;
private static final LocalDateTime maxValue = LocalDateTime.MAX;
private static final long serialVersionUID = 1L; // Add a unique ID to the deserializer if needed
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = p.getText();
return LocalDateTime.parse(value, formatter); // Use the same formatter as in the serializer for consistency
}
}