Jak korzystać z programu mapującego Jackson JSON z Java 8 LocalDateTime?
org.codehaus.jackson.map.JsonMappingException: Nie można utworzyć wystąpienia wartości typu [typ prosty, klasa java.time.LocalDateTime] z ciągu JSON; brak metody konstruktora / fabryki o jednym łańcuchu (poprzez łańcuch referencyjny: MyDTO [„field1”] -> SubDTO [„data”])
Odpowiedzi:
Nie ma potrzeby używania niestandardowych serializatorów / deserializatorów. Użyj modułu datetime dla jackson-modules-java8 :
Ten moduł dodaje obsługę kilku klas:
źródło
registerModule(new JSR310Module())
lubfindAndRegisterModules()
. Zobacz github.com/FasterXML/jackson-datatype-jsr310, a oto, jak dostosować obiekt mapujący, jeśli używasz frameworka Spring: stackoverflow.com/questions/7854030/...OffsetDateTime
@Test
public void testJacksonOffsetDateTimeDeserializer() throws IOException {
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
String json = "\"2015-10-20T11:00:00-8:30\"";
mapper.readValue(json, OffsetDateTime.class);
}
objectMapper.registerModule(new JavaTimeModule());
. Zarówno w przypadku serializacji, jak i deserializacji.Aktualizacja: Pozostawienie tej odpowiedzi ze względów historycznych, ale nie polecam jej. Zobacz zaakceptowaną odpowiedź powyżej.
Powiedz Jacksonowi, aby zmapował za pomocą niestandardowych klas serializacji [de]:
zapewnić niestandardowe klasy:
fakt losowy: jeśli zagnieżdżę się nad klasami i nie ustawię ich w sposób statyczny, komunikat o błędzie jest dziwny:
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
źródło
LocalDateTimeSerializer
LocalDateTimeDeserializer
Jeśli używasz klasy ObjectMapper szybciej-ml, domyślnie ObjectMapper nie rozumie klasy LocalDateTime, więc musisz dodać inną zależność w swoim gradle / maven:
Teraz musisz zarejestrować obsługę typów danych oferowaną przez tę bibliotekę w obiekcie objectmapper. Można to zrobić, wykonując następujące czynności:
Teraz w jsonString możesz łatwo umieścić pole java.LocalDateTime w następujący sposób:
Robiąc to wszystko, konwersja pliku Json na obiekt Java będzie działać poprawnie, możesz odczytać plik, wykonując następujące czynności:
źródło
findAndRegisterModules()
był krytyczny kawałek że brakowało mi podczas konstruowaniaObjectMapper
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
Ta zależność od raju rozwiąże twój problem:
Jedną z rzeczy, z którą się zmagałem, jest zmiana strefy czasowej ZonedDateTime na GMT podczas deserializacji. Okazało się, że domyślnie Jackson zastępuje go jednym z kontekstu. Aby zachować strefę, należy wyłączyć tę „funkcję”
źródło
DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE
musiałem również wyłączyć,SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
aby wszystko zaczęło działać tak, jak powinno.Miałem podobny problem podczas używania rozruchu wiosennego . W przypadku rozruchu wiosennego 1.5.1. ZWOLNIENIEM wystarczyło dodać zależność:
źródło
Jeśli używasz Jersey, musisz dodać zależność Maven (jackson-datatype-jsr310), jak sugerowali inni, i zarejestrować instancję mapowania obiektów w następujący sposób:
Podczas rejestracji Jacksona w swoich zasobach musisz dodać tego mapera w następujący sposób:
źródło
Jeśli nie możesz użyć
jackson-modules-java8
z jakiegokolwiek powodu, możesz (od-) serializować natychmiastowe pole jakolong
użycie@JsonIgnore
i@JsonGetter
&@JsonSetter
:Przykład:
daje
źródło
Używam tego formatu czasu:
"{birthDate": "2018-05-24T13:56:13Z}"
do deserializacji z Jsona do java.time.Instant (patrz zrzut ekranu)źródło
To tylko przykład, jak użyć go w teście jednostkowym, który zhackowałem w celu debugowania tego problemu. Kluczowymi składnikami są
mapper.registerModule(new JavaTimeModule());
<artifactId>jackson-datatype-jsr310</artifactId>
Kod:
źródło
Jeśli używasz Spring boot i masz ten problem z OffsetDateTime, musisz użyć registerModules, jak odpowiedział powyżej @greperror (odpowiedział 28 maja o 13:04), ale zauważ, że jest jedna różnica. Wspomnianej zależności nie trzeba dodawać, ponieważ domyślam się, że wiosenny rozruch już ją ma. Miałem ten problem z wiosennym bootowaniem i działało to dla mnie bez dodawania tej zależności.
źródło
Możesz ustawić to w swoim
application.yml
pliku, aby rozpoznać natychmiastowy czas, czyli Date API w java8:źródło
Dla tych, którzy używają Spring Boot 2.x
Nie trzeba wykonywać żadnej z powyższych czynności - Java 8 LocalDateTime jest serializowany / deserializowany po wyjęciu z pudełka. Musiałem zrobić wszystkie powyższe w 1.x, ale z Boot 2.x działa bezproblemowo.
Zobacz także to odniesienie Format JSON Java 8 LocalDateTime w Spring Boot
źródło
Jeśli ktoś ma problem podczas korzystania z tego
SpringBoot
tutaj, to w jaki sposób naprawiłem problem bez dodawania nowej zależności.W
Spring 2.1.3
Jackson oczekuje, że ciąg daty2019-05-21T07:37:11.000
w tymyyyy-MM-dd HH:mm:ss.SSS
formacie usunie się z serializacjiLocalDateTime
. Upewnij się, że ciąg daty oddziela datę i godzinę, aT
nie znakiemspace
. sekundy (ss
) i milisekundy (SSS
) mogą zostać pominięte.źródło
Jeśli rozważasz użycie fastjson, możesz rozwiązać swój problem, zanotuj wersję
źródło
Jeśli masz ten problem z powodu GraphQL Java Tools i próbujesz uporządkować Javę
Instant
z ciągu daty, musisz skonfigurować SchemaParser, aby używał ObjectMapper w określonych konfiguracjach:W klasie GraphQLSchemaBuilder wstrzyknij ObjectMapper i dodaj te moduły:
i dodaj go do opcji:
Zobacz https://github.com/graphql-java-kickstart/graphql-spring-boot/issues/32
źródło
Jeśli korzystasz z Jackson Serializer , oto sposób na użycie modułów daty:
źródło