Jackson - JsonMappingException (Tidak ada serializer yang ditemukan untuk kelas)

1. Ikhtisar

Dalam tutorial singkat ini, kami akan menganalisis marshalling entitas tanpa getter dan solusi untuk pengecualian Jackson JsonMappingException .

Jika Anda ingin menggali lebih dalam dan mempelajari hal-hal keren lainnya yang dapat Anda lakukan dengan Jackson 2 - lanjutkan ke tutorial utama Jackson.

2. Masalah

Secara default, Jackson 2 hanya akan bekerja dengan bidang yang bersifat publik, atau memiliki metode pengambil publik - membuat serial entitas yang memiliki semua bidang pribadi atau paket pribadi akan gagal :

public class MyDtoNoAccessors { String stringValue; int intValue; boolean booleanValue; public MyDtoNoAccessors() { super(); } // no getters }
@Test(expected = JsonMappingException.class) public void givenObjectHasNoAccessors_whenSerializing_thenException() throws JsonParseException, IOException { String dtoAsString = new ObjectMapper().writeValueAsString(new MyDtoNoAccessors()); assertThat(dtoAsString, notNullValue()); }

The pengecualian penuh adalah:

com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class dtos.MyDtoNoAccessors and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )

3. Solusi

Solusi yang jelas adalah menambahkan getter untuk bidang - jika entitas berada di bawah kendali kami. Jika bukan itu masalahnya dan memodifikasi sumber entitas tidak memungkinkan - maka Jackson memberi kami beberapa alternatif.

3.1. Bidang Deteksi Otomatis Secara Global Dengan Visibilitas Apa Pun

Solusi pertama untuk masalah ini adalah mengkonfigurasi ObjectMapper secara global untuk mendeteksi semua bidang, terlepas dari visibilitasnya:

objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

Ini akan memungkinkan bidang privat dan paket privat dideteksi tanpa getter, dan serialisasi akan bekerja dengan benar:

@Test public void givenObjectHasNoAccessors_whenSerializingWithAllFieldsDetected_thenNoException() throws JsonParseException, IOException { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY); String dtoAsString = objectMapper.writeValueAsString(new MyDtoNoAccessors()); assertThat(dtoAsString, containsString("intValue")); assertThat(dtoAsString, containsString("stringValue")); assertThat(dtoAsString, containsString("booleanValue")); }

3.2. Terdeteksi Semua Bidang di Tingkat Kelas

Opsi lain yang disediakan Jackson 2 adalah - alih-alih konfigurasi global - mengontrol visibilitas bidang di tingkat kelas melalui anotasi @JsonAutoDetect :

@JsonAutoDetect(fieldVisibility = Visibility.ANY) public class MyDtoNoAccessors { ... }

Dengan anotasi ini, serialisasi sekarang harus bekerja dengan benar dengan kelas khusus ini:

@Test public void givenObjectHasNoAccessorsButHasVisibleFields_whenSerializing_thenNoException() throws JsonParseException, IOException { ObjectMapper objectMapper = new ObjectMapper(); String dtoAsString = objectMapper.writeValueAsString(new MyDtoNoAccessors()); assertThat(dtoAsString, containsString("intValue")); assertThat(dtoAsString, containsString("stringValue")); assertThat(dtoAsString, containsString("booleanValue")); }

4. Kesimpulan

Artikel ini mengilustrasikan cara menyiasati visibilitas bidang default di Jackson , dengan mengonfigurasi visibilitas kustom baik secara global di ObjectMapper atau di kelas individual. Jackson memungkinkan penyesuaian lebih lanjut dengan memberikan opsi untuk mengontrol secara tepat bagaimana getter, setter, atau bidang dengan visibilitas spesifik dilihat oleh pembuat peta.

Penerapan semua contoh dan cuplikan kode ini dapat ditemukan di proyek GitHub saya - ini adalah proyek berbasis Eclipse, jadi semestinya mudah untuk mengimpor dan menjalankannya apa adanya.