Wie deserialisiere ich JS-Datum mit Jackson?

72

Ich erhalte eine Datumszeichenfolge von ExtJS im folgenden Format:

2011-04-08T09: 00: 00

Wenn ich versuche, dieses Datum zu deserialisieren, ändert sich die Zeitzone in die indische Standardzeit (fügt der Zeit +5: 30 hinzu). So deserialisiere ich das Datum:

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
getObjectMapper().getDeserializationConfig().setDateFormat(dateFormat);

Dadurch wird auch die Zeitzone nicht geändert. Ich bekomme immer noch das Datum in IST:

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
getObjectMapper().getDeserializationConfig().setDateFormat(dateFormat);

Wie deserialisiere ich das Datum so, wie es ohne die Probleme der Zeitzone kommt?

Varun Achar
quelle

Antworten:

138

Ich habe eine Lösung gefunden, aber damit muss ich den Setter jedes Datums während des gesamten Projekts mit Anmerkungen versehen. Gibt es eine Möglichkeit, das Format beim Erstellen des ObjectMapper anzugeben?

Folgendes habe ich getan:

public class CustomJsonDateDeserializer extends JsonDeserializer<Date>
{
    @Override
    public Date deserialize(JsonParser jsonParser,
            DeserializationContext deserializationContext) throws IOException, JsonProcessingException {

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        String date = jsonParser.getText();
        try {
            return format.parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

    }

}

Und kommentierte die Setter-Methode jedes Datumsfelds folgendermaßen:

@JsonDeserialize(using = CustomJsonDateDeserializer.class)
Varun Achar
quelle
1
Wofür ist das 'T' im Format, sollte es nicht "JJJJ-MM-TT HH: MM: SS" sein
Bryan Hunt
Es ist ein gültiges Datums- / Uhrzeitmuster. Zum Beispiel sogar yyyy.MM.dd G 'at' HH:mm:ss zund hh 'o''clock' a, zzzzsind gültige Muster.
Varun Achar
9
Das 'T' hat das Format, da hierfür der ISO 8601-Standard für die Formatierung von Datum und Uhrzeit verwendet wird. Sie müssen natürlich kein ISO-Standardformat verwenden, dies kann jedoch die Kompatibilität verbessern, wenn Sie Bibliotheken von Drittanbietern wie ExtJS verwenden. en.wikipedia.org/wiki/…
Patrick
7
@jjb NEIN, das ist wirklich falsch. Da simpleDateFormatter nicht threadsicher sind und Jackons Deserializer auf Root-Ebene zwischenspeichern (und dies kann nicht deaktiviert werden), MÜSSEN Sie entweder für jedes Datum einen anderen SimpleDateFormatter verwenden, wie von Varun Achar vorgeschlagen, oder die Deserialisierungsmethode synchronisieren, für die Sie ein Feld verwenden der SimpleDateFormatter. Und dieses Feld kann nicht statisch sein. Dies war einer der schlimmsten Fehler, die ich je gesehen habe.
Snicolas
1
Das war hilfreich, vielen Dank. Da ich Java 8 verwende, habe ich eine Antwort mit LocalDate veröffentlicht (siehe stackoverflow.com/a/31810856/60518) .
Tim Büthe
56

Das funktioniert bei mir - ich benutze Jackson 2.0.4

ObjectMapper objectMapper = new ObjectMapper();
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
objectMapper.setDateFormat(df);
Balaji Natesan
quelle
10
Oder anstelle von SimpleDateFormat verwende ich das neue ISO8601DateFormat (), das mit den Standardeinstellungen der meisten anderen Sprachen (C #, Ruby usw.) übereinstimmt
Christopher Davies,
3
Ist setDateFormat veraltet?
Albert Cheng
2
Ich bin neu bei Jackson. Ich frage mich, wo ich den obigen Code hinzufügen soll.
Harbir
2
'objectMapper.setDateFormat (df);' ist gut, wenn Sie nur ein Dienstprogramm oder eine eindeutige Bean haben, in der Sie das Format festlegen. Andernfalls müssen Sie immer daran denken, es überall dort festzulegen, wo Sie es verwenden. Außerdem ist DateFormat nicht threadsicher!
Giuseppe Adaldo
1
ObjectMapperist threadsicher. Sie benötigen für jede Konfiguration nur eine Instanz davon. Wenn Sie also zwei verschiedene Datumsformate benötigen ObjectMapper, benötigen Sie zwei Objekte oder nur eines, aber Sie müssen synchronizedie setDateFormatMethode aufrufen .
Varun Achar
15

Zu diesem Thema gibt es einen guten Blog: http://www.baeldung.com/jackson-serialize-dates Die Verwendung von @JsonFormat sieht am einfachsten aus.

public class Event {
    public String name;

    @JsonFormat
      (shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
    public Date eventDate;
}
Wangf
quelle
6

Zusätzlich zu Varun Achars Antwort ist dies die Java 8-Variante, die ich mir ausgedacht habe und die java.time.LocalDate und ZonedDateTime anstelle der alten Klassen java.util.Date verwendet.

public class LocalDateDeserializer extends JsonDeserializer<LocalDate> {

    @Override
    public LocalDate deserialize(JsonParser jsonparser, DeserializationContext deserializationcontext) throws IOException {

        String string = jsonparser.getText();

        if(string.length() > 20) {
            ZonedDateTime zonedDateTime = ZonedDateTime.parse(string);
            return zonedDateTime.toLocalDate();
        }

        return LocalDate.parse(string);
    }
  }
Tim Büthe
quelle
2
Möglicherweise können Sie das JSR-310-Datentypmodul von Jackson konfigurieren und verwenden, anstatt Ihren eigenen Deserializer zu schreiben.
Paul
-2

@JsonFormat funktioniert nur für das Standardformat, das von der von Ihnen verwendeten Jackson-Version unterstützt wird.

Bsp.: - kompatibel mit allen Standardformen ("JJJJ-MM-TT'T'HH: mm: ss.SSSZ", "JJJJ-MM-TT'T'HH: mm: ss.SSS'Z '", ") EEE, TT MMM JJJJ HH: MM: SS zzz "," JJJJ-MM-TT ")) für Jackson 2.8.6

Jay Patel
quelle