Saya tidak pernah bisa membuat ini berfungsi sederhana menggunakan anotasi. Untuk membuatnya berfungsi, saya membuat ContextResolver
untuk ObjectMapper
, lalu saya menambahkan JSR310Module
( pembaruan: sekarang sebagai JavaTimeModule
gantinya ), bersama dengan satu peringatan lagi, yang merupakan kebutuhan untuk mengatur write-date-as-timestamp menjadi false. Lihat lebih lanjut di dokumentasi untuk modul JSR310 . Ini adalah contoh dari apa yang saya gunakan.
Ketergantungan
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.4.0</version>
</dependency>
Catatan: Satu masalah yang saya hadapi dengan ini adalah bahwa jackson-annotation
versi ditarik oleh ketergantungan lain, menggunakan versi 2.3.2, yang membatalkan 2.4 yang diperlukan oleh jsr310
. Apa yang terjadi adalah saya mendapat NoClassDefFound untuk ObjectIdResolver
, yang merupakan kelas 2.4. Jadi saya hanya perlu berbaris versi ketergantungan yang disertakan
ContextResolver
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JSR310Module;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
private final ObjectMapper MAPPER;
public ObjectMapperContextResolver() {
MAPPER = new ObjectMapper();
// Now you should use JavaTimeModule instead
MAPPER.registerModule(new JSR310Module());
MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return MAPPER;
}
}
Kelas sumber daya
@Path("person")
public class LocalDateResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getPerson() {
Person person = new Person();
person.birthDate = LocalDate.now();
return Response.ok(person).build();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createPerson(Person person) {
return Response.ok(
DateTimeFormatter.ISO_DATE.format(person.birthDate)).build();
}
public static class Person {
public LocalDate birthDate;
}
}
Uji
curl -v http://localhost:8080/api/person
Hasil: {"birthDate":"2015-03-01"}
curl -v -POST -H "Content-Type:application/json" -d "{\"birthDate\":\"2015-03-01\"}" http://localhost:8080/api/person
Hasil: 2015-03-01
Lihat juga di sini untuk solusi JAXB.
MEMPERBARUI
Itu JSR310Module
sudah ditinggalkan pada versi 2.7 dari Jackson. Sebagai gantinya, Anda harus mendaftarkan modul JavaTimeModule
. Masih ketergantungan yang sama.
getContext
metode ini. Jika metode ini dipanggil, saya tidak melihat alasan untuk ini tidak berhasil. Jika tidak dipanggil, maka itu mungkin sesuatu yang perlu diperbaiki dengan konfigurasi aplikasi. Untuk itu saya perlu melihat lebih dari apa yang Anda berikan. Seperti versi Resteasy, dependensi, konfigurasi aplikasi baik web.xml atau subkelas Aplikasi. Pada dasarnya cukup untuk mereproduksi masalahObjectMapper
seperti yang dilakukan oleh angkuh (Anda dapat melihat tautan dalam pertanyaan). Saya tidak tahu karena saya tidak banyak bekerja dengan angkuh. Tapi saya pikir kesombongan adalah masalah utama, mengapa contextresolver tidak dipanggil.@JsonSerialize dan @JsonDeserialize bekerja dengan baik untuk saya. Mereka menghilangkan kebutuhan untuk mengimpor modul jsr310 tambahan:
Deserializer:
Serializer:
sumber
jackson-datatype-jsr310
. Tidak perlu menentukannya secara manual di proyek Anda.jackson-datatype-jsr310
.bekerja dengan baik untuk saya.
sumber
new com.fasterxml.jackson.datatype.jsr310.JSR310Module()
untuk versi 2.5.4 dari Jackson. Kelas JavaTimeModule tidak ada di versi ini.LocalDateTime
(jackson 2.9.5). 1 ketergantungan tambahan diperlukan, jadi build.sbt saya terlihat seperti:"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.9.5", "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.5"
Di aplikasi web Spring Boot, dengan versi Jackson dan JSR 310 "2.8.5"
@JsonFormat
Karya - karya:sumber
@JsonDeserialize(using= LocalDateDeserializer.class)
@JsonFormat
hanya untuk mengubah format data output. stackoverflow.com/a/53251526/816759 bekerja sempurna dengan@JsonFormat
,@JsonDeserialize
,@JsonSerialize
spring.jackson.serialization.write-dates-as-timestamps=false
ke Andaapplication.properties
, dan memformatnyayyyy-MM-dd
secara otomatis. Tidak perlu@JsonFormat
Solusi paling sederhana (yang mendukung deserialisasi dan serialisasi juga) adalah
Saat menggunakan dependensi berikut dalam proyek Anda.
Maven
Gradle
Tidak ada implementasi tambahan dari ContextResolver, Serializer atau Deserializer diperlukan.
sumber
ObjectMapper
belumJavaTimeModule
mendaftar. Jika instance ObjectMapper Anda disediakan dari pegas / MessageConverter framework. Mereka melakukan sihir untuk menghubungkan mereka. Dalam kasus lain, harusregisterModule
mengaktifkanLocalDateDeserializer
secara default untuk semua "LocalDate" di POJOSejak
LocalDateSerializer
mengubahnya menjadi "[tahun, bulan, hari]" "(array json) daripada" tahun-bulan-hari "(string json) secara default, dan karena saya tidak ingin memerlukanObjectMapper
pengaturan khusus (Anda dapat makeLocalDateSerializer
menghasilkan string jika Anda menonaktifkanSerializationFeature.WRITE_DATES_AS_TIMESTAMPS
tetapi yang memerlukan setup tambahan untuk AndaObjectMapper
), saya menggunakan yang berikut:impor:
kode:
Dan sekarang saya bisa menggunakan
new ObjectMapper()
untuk membaca dan menulis objek saya tanpa pengaturan khusus.sumber
"2018-12-07"
alih-alih"2018-12-7"
Anda akan mendapatkan kesalahan.yyyy-MM-dd
format (2 digit bulan dan hari), bukan formatyyyy-M-d
(1 digit bulan atau hari).Hanya pembaruan dari jawaban Christopher.
Sejak versi 2.6.0
Gunakan JavaTimeModule alih-alih JSR310Module (usang).
Menurut dokumentasi , JavaTimeModule baru menggunakan pengaturan standar yang sama untuk default ke serialisasi yang TIDAK menggunakan Id Zona Waktu, dan sebaliknya hanya menggunakan offset Timezone yang sesuai dengan ISO-8601.
Perilaku dapat diubah menggunakan SerializationFeature.WRITE_DATES_WITH_ZONE_ID
sumber
MAPPER.registerModule(new JavaTimeModule());
baris. Itu membiarkan saya memformat objek LocalDate sebagai format "2020-02-20". Saya tidak membutuhkanMAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
Anotasi berikut bekerja dengan baik untuk saya.
Tidak diperlukan dependensi tambahan.
sumber
sumber
https://stackoverflow.com/a/53251526/1282532 adalah cara paling sederhana untuk membuat serialisasi / deserialize properti. Saya memiliki dua keprihatinan tentang pendekatan ini - sampai beberapa titik pelanggaran prinsip KERING dan penggandengan tinggi antara pojo dan mapper.
Jika Anda memiliki POJO dengan beberapa bidang LocalDate lebih baik untuk mengkonfigurasi mapper daripada POJO. Ini bisa sesederhana https://stackoverflow.com/a/35062824/1282532 jika Anda menggunakan nilai ISO-8601 ("2019-01-31")
Jika Anda perlu menangani format khusus, kodenya akan seperti ini:
Logikanya ditulis sekali saja, dapat digunakan kembali untuk beberapa POJO
sumber
Paling sederhana dan terpendek sejauh ini:
tidak diperlukan ketergantungan dengan booting Spring> = 2.2+
sumber
Pada tahun 2020 dan Jackson 2.10.1 tidak perlu kode khusus, hanya masalah memberi tahu Jackson apa yang Anda inginkan:
Ini telah disebutkan dalam jawaban ini , saya menambahkan tes unit memverifikasi fungsi:
TestBean menggunakan Lombok untuk menghasilkan boilerplate untuk kacang.
sumber
Di kelas konfigurasi, tentukan kelas LocalDateSerializer dan LocalDateDeserializer dan daftarkan mereka ke ObjectMapper melalui JavaTimeModule seperti di bawah ini:
sumber
Jika permintaan Anda mengandung objek seperti ini:
Maka Anda dapat menggunakan:
Di atas lapangan:
Kodenya ada di Kotlin tetapi tentu saja ini juga bisa digunakan untuk Java.
sumber