Jackson - JsonMappingException (Tidak terdapat serializer untuk kelas)

1. Gambaran keseluruhan

Dalam tutorial ringkas ini, kami akan menganalisis pengumpulan entiti tanpa pemenang dan penyelesaian untuk pengecualian Jackson JsonMappingException .

Sekiranya anda ingin menggali lebih mendalam dan mengetahui perkara menarik lain yang boleh anda lakukan dengan Jackson 2 - teruskan ke tutorial utama Jackson.

2. Masalahnya

Secara lalai, Jackson 2 hanya akan berfungsi dengan bidang yang bersifat awam, atau mempunyai kaedah mendapatkan awam - membuat siri entiti yang mempunyai semua bidang peribadi atau paket peribadi 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 ialah:

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. Penyelesaiannya

Penyelesaian yang jelas adalah dengan menambah pemenang ladang - jika entiti berada di bawah kawalan kami. Sekiranya itu tidak berlaku dan mengubah sumber entiti tidak mungkin - maka Jackson memberi kami beberapa alternatif.

3.1. Medan Mengesan Auto secara global dengan sebarang penglihatan

Penyelesaian pertama untuk masalah ini ialah mengkonfigurasi ObjectMapper secara global untuk mengesan semua bidang, tanpa mengira keterlihatannya:

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

Ini akan membolehkan medan persendirian dan pakej peribadi dikesan tanpa pemula, dan penyirian akan berfungsi dengan betul:

@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. Mengesan Semua Medan di Tingkat Kelas

Pilihan lain yang diberikan oleh Jackson 2 adalah - bukannya konfigurasi global - mengawal keterlihatan lapangan di peringkat kelas melalui anotasi @JsonAutoDetect :

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

Dengan penjelasan ini, penggambaran sekarang seharusnya berfungsi dengan betul dengan kelas tertentu 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 menggambarkan cara mengatasi jarak pandang bidang lalai di Jackson , dengan mengkonfigurasi keterlihatan khusus baik secara global pada ObjectMapper atau pada kelas individu. Jackson membenarkan penyesuaian lebih jauh lagi dengan memberikan pilihan untuk mengawal dengan tepat bagaimana pengawal, pengatur atau bidang dengan penglihatan tertentu dilihat oleh pemeta.

Pelaksanaan semua contoh dan potongan kode ini terdapat di projek GitHub saya - ini adalah projek berasaskan Eclipse, jadi mudah untuk diimport dan dijalankan sebagaimana adanya.