199 votes

Format de la date Mappage vers JSON Jackson

J'ai un format de date provenant de l'API comme ceci :

"start_time": "2015-10-1 3:00 PM GMT+1:00"

Il s'agit de l'horodatage YYYY-DD-MM HH:MM am/pm GMT. Je fais correspondre cette valeur à une variable Date dans POJO. Évidemment, il y a une erreur de conversion.

Je voudrais savoir 2 choses :

  1. Quel est le formatage que je dois utiliser pour effectuer la conversion avec Jackson ? La date est-elle un bon type de champ pour cela ?
  2. En général, existe-t-il un moyen de traiter les variables avant qu'elles ne soient mappées aux membres de l'objet par Jackson ? Par exemple, en modifiant le format, les calculs, etc.

416voto

Depuis Jackson v2.0, vous pouvez utiliser l'annotation @JsonFormat directement sur les membres Object ;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm a z")
private Date date;

161voto

pb2q Points 28514

Quel est le formatage que je dois utiliser pour effectuer la conversion avec Jackson ? La date est-elle un bon type de champ pour cela ?

Date est un bon type de champ pour cela. Vous pouvez rendre le JSON analysable assez facilement en utilisant l'option ObjectMapper.setDateFormat :

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
myObjectMapper.setDateFormat(df);

En général, existe-t-il un moyen de traiter les variables avant qu'elles ne soient mappées aux membres de l'objet par Jackson ? Par exemple, en modifiant le format, les calculs, etc.

Oui. Vous avez plusieurs options, y compris l'implémentation d'un système personnalisé de JsonDeserializer , par exemple en prolongeant JsonDeserializer<Date> . Ce site est un bon début.

62voto

Miklos Krivan Points 166

Bien sûr. il existe un moyen automatisé appelé sérialisation et désérialisation et vous pouvez le définir avec des annotations spécifiques ( @JsonSerialize , @JsonDeserialize ) comme l'a également mentionné pb2q.

Vous pouvez utiliser à la fois java.util.Date et java.util.Calendar. ... et probablement aussi JodaTime.

Les annotations @JsonFormat n'ont pas fonctionné pour moi comme je le voulais. (il a ajusté le fuseau horaire à une valeur différente) pendant la désérialisation (la sérialisation a fonctionné parfaitement) :

@JsonFormat(locale = "hu", shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "CET")

@JsonFormat(locale = "hu", shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "Europe/Budapest")

Vous devez utiliser un sérialiseur et un désérialiseur personnalisés au lieu de l'annotation @JsonFormat si vous voulez un résultat prédictif. J'ai trouvé un très bon tutoriel et une bonne solution ici. http://www.baeldung.com/jackson-serialize-dates

Il existe des exemples pour Date mais j'avais besoin de Calendrier champs ainsi voici mon implémentation :

El sérialiseur classe :

public class CustomCalendarSerializer extends JsonSerializer<Calendar> {

    public static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    public static final Locale LOCALE_HUNGARIAN = new Locale("hu", "HU");
    public static final TimeZone LOCAL_TIME_ZONE = TimeZone.getTimeZone("Europe/Budapest");

    @Override
    public void serialize(Calendar value, JsonGenerator gen, SerializerProvider arg2)
            throws IOException, JsonProcessingException {
        if (value == null) {
            gen.writeNull();
        } else {
            gen.writeString(FORMATTER.format(value.getTime()));
        }
    }
}

El désérialiseur classe :

public class CustomCalendarDeserializer extends JsonDeserializer<Calendar> {

    @Override
    public Calendar deserialize(JsonParser jsonparser, DeserializationContext context)
            throws IOException, JsonProcessingException {
        String dateAsString = jsonparser.getText();
        try {
            Date date = CustomCalendarSerializer.FORMATTER.parse(dateAsString);
            Calendar calendar = Calendar.getInstance(
                CustomCalendarSerializer.LOCAL_TIME_ZONE, 
                CustomCalendarSerializer.LOCALE_HUNGARIAN
            );
            calendar.setTime(date);
            return calendar;
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}

et l'utilisation des classes ci-dessus :

public class CalendarEntry {

    @JsonSerialize(using = CustomCalendarSerializer.class)
    @JsonDeserialize(using = CustomCalendarDeserializer.class)
    private Calendar calendar;

    // ... additional things ...
}

Avec cette mise en œuvre, l'exécution du processus de sérialisation et de désérialisation donne consécutivement la valeur d'origine.

En utilisant uniquement l'annotation @JsonFormat, la désérialisation donne un résultat différent. Je pense que c'est à cause de la configuration par défaut du fuseau horaire interne de la bibliothèque que vous ne pouvez pas modifier avec les paramètres d'annotation (c'est ce que j'ai constaté avec les versions 2.5.3 et 2.6.3 de la bibliothèque Jackson).

21voto

Odwori Points 449

Pour ajouter des caractères tels que T et Z dans votre date

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private Date currentTime;

sortie

{
    "currentTime": "2019-12-11T11:40:49Z"
}

6voto

BaiJiFeiLong Points 498

Un exemple complet pour botte de printemps application avec RFC3339 format date-heure

package bj.demo;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;

import java.text.SimpleDateFormat;

/**
 * Created by BaiJiFeiLong@gmail.com at 2018/5/4 10:22
 */
@SpringBootApplication
public class BarApp implements ApplicationListener<ApplicationReadyEvent> {

    public static void main(String[] args) {
        SpringApplication.run(BarApp.class, args);
    }

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X