Bagaimana cara menggunakan mapper Jackson JSON dengan Java 8 LocalDateTime?
org.codehaus.jackson.map.JsonMappingException: Tidak dapat membuat instantiate nilai tipe [tipe sederhana, kelas java.time.LocalDateTime] dari JSON String; tidak ada metode String-konstruktor / pabrik tunggal (melalui rantai referensi: MyDTO ["field1"] -> SubDTO ["date"])
Jawaban:
Tidak perlu menggunakan serializers / deserializers khusus di sini. Gunakan modul datetime jackson-modules-java8 :
Modul ini menambahkan dukungan untuk beberapa kelas:
sumber
registerModule(new JSR310Module())
ataufindAndRegisterModules()
. Lihat github.com/FasterXML/jackson-datatype-jsr310 dan di sini adalah bagaimana menyesuaikan objek mapper Anda jika Anda menggunakan kerangka kerja 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());
. Baik pada serialisasi dan deserialisasi.Pembaruan: Meninggalkan jawaban ini karena alasan historis, tetapi saya tidak merekomendasikannya. Silakan lihat jawaban yang diterima di atas.
Beri tahu Jackson untuk memetakan menggunakan kelas serialisasi kustom [de] Anda:
menyediakan kelas khusus:
fakta acak: jika saya bersarang di atas kelas dan tidak membuatnya statis, pesan kesalahannya aneh:
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
sumber
LocalDateTimeSerializer
danLocalDateTimeDeserializer
Jika Anda menggunakan kelas ObjectMapper dari fastxml, secara default ObjectMapper tidak memahami kelas LocalDateTime, jadi, Anda perlu menambahkan dependensi lain di gradle / maven Anda:
Sekarang Anda perlu mendaftarkan dukungan tipe data yang ditawarkan oleh perpustakaan ini ke objek Anda objectmapper, ini dapat dilakukan dengan mengikuti:
Sekarang, di jsonString Anda, Anda dapat dengan mudah menempatkan bidang java.LocalDateTime Anda sebagai berikut:
Dengan melakukan semua ini, konversi file Json ke Java Anda akan berfungsi dengan baik, Anda dapat membaca file dengan mengikuti:
sumber
findAndRegisterModules()
adalah bagian penting yang hilang bagi saya ketika membangun sebuahObjectMapper
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
Ketergantungan pakar ini akan memecahkan masalah Anda:
Satu hal yang saya perjuangkan adalah zona waktu ZonedDateTime diubah menjadi GMT selama deserialisasi. Ternyata, bahwa secara default jackson menggantinya dengan satu dari konteks .. Untuk menjaga zona satu harus menonaktifkan 'fitur' ini
sumber
DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE
saya juga harus menonaktifkanSerializationFeature.WRITE_DATES_AS_TIMESTAMPS
agar semuanya mulai berfungsi sebagaimana mestinya.Saya memiliki masalah yang sama saat menggunakan boot Spring . Dengan Spring boot 1.5.1.RELEASE yang harus saya lakukan adalah menambahkan ketergantungan:
sumber
Jika Anda menggunakan Jersey maka Anda perlu menambahkan dependensi Maven (jackson-datatype-jsr310) seperti yang disarankan orang lain dan mendaftarkan instance mapper objek Anda seperti:
Saat mendaftarkan Jackson di sumber daya Anda, Anda perlu menambahkan mapper ini seperti:
sumber
Jika Anda tidak dapat menggunakan
jackson-modules-java8
untuk alasan apa pun, Anda dapat (membatalkan) membuat serialisasi bidang instanlong
menggunakan@JsonIgnore
dan@JsonGetter
&@JsonSetter
:Contoh:
hasil panen
sumber
Saya menggunakan format waktu ini:
"{birthDate": "2018-05-24T13:56:13Z}"
untuk deserialize dari json ke java.time.Instant (lihat screenshot)sumber
Ini hanyalah contoh cara menggunakannya dalam unit test yang saya retas untuk men-debug masalah ini. Bahan utamanya adalah
mapper.registerModule(new JavaTimeModule());
<artifactId>jackson-datatype-jsr310</artifactId>
Kode:
sumber
Jika Anda menggunakan boot Spring dan memiliki masalah ini dengan OffsetDateTime maka perlu menggunakan registerModules seperti yang dijawab di atas oleh @greperror (dijawab 28 Mei 16 pada 13:04) tetapi perhatikan bahwa ada satu perbedaan. Ketergantungan yang disebutkan tidak perlu ditambahkan karena saya menduga boot spring sudah memilikinya. Saya mengalami masalah dengan boot Spring dan ini berhasil untuk saya tanpa menambahkan ketergantungan ini.
sumber
Anda dapat mengatur ini di
application.yml
file Anda untuk menyelesaikan waktu Instan, yang merupakan API Tanggal di java8:sumber
Bagi yang menggunakan Spring Boot 2.x
Tidak perlu melakukan hal di atas - Java 8 LocalDateTime adalah serial / de-serial keluar dari kotak. Saya harus melakukan semua hal di atas dalam 1.x, tetapi dengan Boot 2.x, ia berfungsi dengan mulus.
Lihat referensi ini juga format JSON Java 8 LocalDateTime di Spring Boot
sumber
Jika ada yang mengalami masalah saat menggunakan di
SpringBoot
sini adalah bagaimana saya memperbaiki masalah tanpa menambahkan ketergantungan baru.Dalam
Spring 2.1.3
Jackson mengharapkan string tanggal2019-05-21T07:37:11.000
dalamyyyy-MM-dd HH:mm:ss.SSS
format ini untuk de-serialisasi dalamLocalDateTime
. Pastikan string tanggal memisahkan tanggal dan waktu denganT
tidak denganspace
. detik (ss
) dan milidetik (SSS
) dapat dinonaktifkan.sumber
Jika Anda mempertimbangkan untuk menggunakan fastjson, Anda dapat menyelesaikan masalah Anda, catat versinya
sumber
Jika Anda mengalami masalah ini karena GraphQL Java Tools dan mencoba
Instant
menyusun Java dari string tanggal, Anda perlu mengatur SchemaParser Anda untuk menggunakan ObjectMapper dengan konfigurasi tertentu:Di kelas GraphQLSchemaBuilder Anda, suntikkan ObjectMapper dan tambahkan modul ini:
dan tambahkan ke opsi:
Lihat https://github.com/graphql-java-kickstart/graphql-spring-boot/issues/32
sumber
Jika Anda menggunakan Jackson Serializer , berikut adalah cara menggunakan modul tanggal:
sumber