Mam format daty pochodzący z API w następujący sposób:
"start_time": "2015-10-1 3:00 PM GMT+1:00"
Który jest RRRR-DD-MM HH: MM Am / pm GMT timestamp. Mapuję tę wartość do zmiennej Date w POJO. Oczywiście pokazuje błąd konwersji.
Chciałbym wiedzieć 2 rzeczy:
- Jakiego formatowania potrzebuję, aby przeprowadzić konwersję w Jackson? Czy data jest dobrym typem pola do tego celu?
- Ogólnie rzecz biorąc, czy istnieje sposób na przetworzenie zmiennych, zanim zostaną zmapowane do elementów Object przez Jacksona? Coś jak zmiana formatu, obliczenia itp.
Date
klasy. java.time, nowoczesny interfejs API daty i czasu Javy, zastąpił go prawie 5 lat temu. Użyj go i FasterXML / jackson-modules-java8 .Odpowiedzi:
Date
jest do tego dobrym typem pola. Możesz łatwo przeprowadzić analizę JSON, używającObjectMapper.setDateFormat
:Tak. Masz kilka opcji, w tym zaimplementowanie niestandardowego
JsonDeserializer
, npJsonDeserializer<Date>
. Rozszerzenie . To dobry początek.źródło
LocalDateTime
czyZonedDateTime
zamiastDate
? PonieważDate
jest zasadniczo przestarzały (lub przynajmniej wiele jego metod), chciałbym użyć tych alternatyw.java.util.Date
wyraźnie, chcę zaznaczyć, że to nie działa w przypadkujava.sql.Date.
Zobacz także moją odpowiedź poniżej.Od wersji Jackson 2.0 możesz używać adnotacji @JsonFormat bezpośrednio na członkach Object;
źródło
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone="GMT")
Oczywiście istnieje zautomatyzowany sposób zwany serializacją i deserializacją i można go zdefiniować za pomocą określonych adnotacji ( @JsonSerialize , @JsonDeserialize ), o czym również wspomina pb2q.
Możesz użyć zarówno java.util.Date, jak i java.util.Calendar ... i prawdopodobnie również JodaTime.
Adnotacje @JsonFormat nie działały tak, jak chciałem ( dostosowały strefę czasową do innej wartości) podczas deserializacji (serializacja działała idealnie):
Jeśli chcesz przewidzieć wynik, musisz użyć niestandardowego serializatora i niestandardowego deserializatora zamiast adnotacji @JsonFormat. Znalazłem naprawdę dobry samouczek i rozwiązanie tutaj http://www.baeldung.com/jackson-serialize-dates
Istnieją przykłady pól daty, ale potrzebowałem pól kalendarza, więc oto moja implementacja :
Serializer klasa:
Deserializator klasa:
i wykorzystanie powyższych klas:
Korzystając z tej implementacji, wykonanie procesu serializacji i deserializacji kolejno powoduje uzyskanie wartości pochodzenia.
Tylko przy użyciu adnotacji @JsonFormat deserializacja daje inny wynik. Myślę, że z powodu domyślnej konfiguracji wewnętrznej strefy czasowej biblioteki, czego nie można zmienić za pomocą parametrów adnotacji (takie było również moje doświadczenie z biblioteką Jacksona w wersji 2.5.3 i 2.6.3).
źródło
Kompletny przykład aplikacji rozruchu sprężynowego w
RFC3339
formacie datetimeźródło
Aby dodać znaki, takie jak T i Z, do daty
wynik
źródło
Pracuje dla mnie. SpringBoot.
wynik:
źródło
Opierając się na bardzo pomocnej odpowiedzi @ miklov-kriven, mam nadzieję, że te dwa dodatkowe punkty do rozważenia okażą się pomocne dla kogoś:
(1) Uważam, że dobrym pomysłem jest włączenie serializatora i deserializatora jako statycznych klas wewnętrznych w tej samej klasie. Uwaga: użycie ThreadLocal do zabezpieczenia wątków SimpleDateFormat.
(2) Jako alternatywę dla używania adnotacji @JsonSerialize i @JsonDeserialize na każdym elemencie klasy możesz również rozważyć nadpisanie domyślnej serializacji Jacksona poprzez zastosowanie niestandardowej serializacji na poziomie aplikacji, czyli wszyscy członkowie klasy typu Date zostaną serializowani przez Jacksona przy użyciu tej niestandardowej serializacji bez jawnej adnotacji w każdym polu. Jeśli na przykład używasz Spring Boot, jeden ze sposobów na to wygląda następująco:
źródło
Jeśli ktoś ma problemy z użyciem niestandardowego formatu daty dla java.sql.Date, to jest to najprostsze rozwiązanie:
(Ta odpowiedź SO zaoszczędziła mi wielu problemów: https://stackoverflow.com/a/35212795/3149048 )
Jackson domyślnie używa SqlDateSerializer dla java.sql.Date, ale obecnie ten serializator nie bierze pod uwagę formatu daty, zobacz ten problem: https://github.com/FasterXML/jackson-databind/issues/1407 . Aby obejść ten problem, należy zarejestrować inny serializator dla java.sql.Date, jak pokazano w przykładzie kodu.
źródło
Chcę zaznaczyć, że ustawienie
SimpleDateFormat
polubienia opisanego w drugiej odpowiedzi działa tylko w przypadku,java.util.Date
gdy zakładam, że chodzi o to pytanie. Alejava.sql.Date
formater nie działa. W moim przypadku nie było zbyt oczywiste, dlaczego formater nie działał, ponieważ w modelu, który powinien być serializowany, pole było w rzeczywistości a,java.utl.Date
ale rzeczywisty obiekt ostatecznie był ajava.sql.Date
. Jest to możliwe, ponieważWięc to jest rzeczywiście ważne
Więc jeśli zastanawiasz się, dlaczego twoje pole Data nie jest poprawnie sformatowane, upewnij się, że obiekt to naprawdę
java.util.Date
.Tutaj również wspomniano, dlaczego obsługa
java.sql.Date
nie zostanie dodana.źródło
Date
klas. Jednak obecnie nie powinno się żadnego z nich ani teżSimpleDateFormat
. java.time, nowoczesny interfejs API daty i czasu w Javie, zastąpił je prawie 5 lat temu. Użyj go i FasterXML / jackson-modules-java8 .