Lorsque nous travaillons avec Java 8
Time
et Jackson
Une bonne idée est d'utiliser jackson-modules-java8 qui propose de nombreux sérialiseurs et désérialiseurs prêts à l'emploi. Pour l'activer, nous devons enregistrer JavaTimeModule
module. Pour sérialiser Instant
InstantSerializer est utilisé. Lorsque nous vérifions comment il est mis en œuvre, nous découvrons que derrière la scène DecimalUtils.toDecimal est utilisée. Il semble qu'il y ait toujours des zéros ajoutés à la fin de la valeur des nanosecondes.
Nous pouvons écrire notre InstantSerializer
qui le sérialise de la manière souhaitée. Parce que les classes de ce projet ne sont pas prêtes à être facilement étendues, nous devons implémenter de nombreuses méthodes et constructeurs indésirables. Nous devons également créer dans notre projet com.fasterxml.jackson.datatype.jsr310.ser
et y créer notre implémentation. Voir l'exemple ci-dessous :
package com.fasterxml.jackson.datatype.jsr310.ser;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
public class ShortInstantSerializer extends InstantSerializerBase<Instant> {
private ToLongFunction<Instant> getEpochSeconds = Instant::getEpochSecond;
private ToIntFunction<Instant> getNanoseconds = i -> i.getNano() / 1_000_000;
public ShortInstantSerializer() {
super(Instant.class, Instant::toEpochMilli, Instant::getEpochSecond, Instant::getNano, null);
}
protected ShortInstantSerializer(ShortInstantSerializer base, Boolean useTimestamp, Boolean useNanoseconds, DateTimeFormatter formatter) {
super(base, useTimestamp, useNanoseconds, formatter);
}
@Override
protected JSR310FormattedSerializerBase<?> withFormat(Boolean useTimestamp, DateTimeFormatter formatter, JsonFormat.Shape shape) {
return new ShortInstantSerializer(this, useTimestamp, null, formatter);
}
@Override
public void serialize(Instant value, JsonGenerator generator, SerializerProvider provider) throws IOException {
if (useTimestamp(provider)) {
if (useNanoseconds(provider)) {
generator.writeNumber(new BigDecimal(toShortVersion(value)));
return;
}
}
super.serialize(value, generator, provider);
}
private String toShortVersion(final Instant value) {
return getEpochSeconds.applyAsLong(value) + "." + padWithZeros(getNanoseconds.applyAsInt(value));
}
private String padWithZeros(final int value) {
return String.format("%1$3s", String.valueOf(value)).replace(' ', '0');
}
}
Et des exemples pour l'utiliser :
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.ShortInstantSerializer;
import java.time.Instant;
public class JsonApp {
public static void main(String[] args) throws Exception {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(Instant.class, new ShortInstantSerializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(javaTimeModule);
mapper.disable(SerializationFeature.INDENT_OUTPUT);
System.out.println(mapper.writeValueAsString(new Element()));
}
}
class Element {
private Instant timestamp = Instant.now();
public Instant getTimestamp() {
return timestamp;
}
public void setTimestamp(Instant timestamp) {
this.timestamp = timestamp;
}
}
Le code ci-dessus s'imprime :
{"timestamp":1559074287.223}
Si vous voulez vous débarrasser de tous les zéros dans tous les cas, écrivez votre propre programme. getNanoseconds
déclarée dans ShortInstantSerializer
classe.