Serializing with Jackson (JSON) - mendapatkan “No serializer found”?


262

Saya mendapatkan pengecualian ketika mencoba membuat serial objek yang sangat sederhana menggunakan Jackson. Kesalahan:

org.codehaus.jackson.map.JsonMappingException: Tidak ada serializer yang ditemukan untuk kelas MyPackage.TestA dan tidak ada properti yang ditemukan untuk membuat BeanSerializer (untuk menghindari pengecualian, nonaktifkan SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS))

Di bawah ini adalah kelas dan kode sederhana untuk diserialisasi.

Adakah yang bisa memberitahu saya mengapa saya mendapatkan kesalahan ini?

public class TestA {
    String SomeString = "asd";
}

TestA testA = new TestA();
ObjectMapper om = new ObjectMapper();
try {
    String testAString = om.writeValueAsString(testA); // error here!

    TestA newTestA = om.readValue(testAString, TestA.class);
} catch (JsonGenerationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (JsonMappingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Saya menulis posting tentang Cara Menulis Serializer Kustom dengan Jackson yang mungkin bermanfaat bagi sebagian orang.
Sam Berry

Jawaban:


329

Seperti yang sudah dijelaskan, konfigurasi default sebuah ObjectMapperinstance adalah hanya mengakses properti yang merupakan bidang publik atau memiliki getter / setter publik. Alternatif untuk mengubah definisi kelas untuk membuat bidang menjadi publik atau untuk menyediakan pengambil / penyetel publik adalah dengan menetapkan (ke dasar VisibilityChecker) aturan visibilitas properti yang berbeda. Jackson 1.9 menyediakan ObjectMapper.setVisibility()metode kenyamanan untuk melakukannya. Sebagai contoh dalam pertanyaan awal, saya kemungkinan akan mengkonfigurasi ini sebagai

myObjectMapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

Untuk Jackson> 2.0:

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

Untuk informasi lebih lanjut dan detail tentang opsi konfigurasi terkait, saya sarankan meninjau JavaDocs aktifObjectMapper.setVisibility() .


59
Ini berhasil untuk saya. Pada Jackson 2.0, ObjectMapper # setVisibility mengambil PropertyAccessor sebagai argumen pertama. Oneliner yang setara adalah myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Dan Robinson

@DanRobinson saya menggunakan yang sama. Tapi sebenarnya saya menghasilkan file yaml. jadi untuk JSONString sebagai: {"term":{"call_failed":"true"}}itu menghasilkan struktur yaml sebagai: filter: map: term: map: call_failed: "true"Mengapa menghasilkan mapkata kunci? Bagaimana saya bisa menghapusnya?
Manish Kumar

7
Saya mungkin menghabiskan 8 jam dengan kesalahan ini, tidak menyadari bahwa metode pengambil saya tidak memiliki "publik" di atasnya..bodoh
Mike Kellogg

1
Saya mendapatkan kesalahan ini saat mengubah ClientResponse ke string menggunakan object mapper
VdeX

1
Anda juga dapat menambahkan anotasi di @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)atas kelas Anda
veben

74

Agar Jackson membuat cerita bersambung dari kelas itu, SomeStringfield harus berupa public(sekarang isolasi tingkat paket) atau Anda perlu mendefinisikan metode pengambil dan penyetel untuknya.


5
Harap perhatikan bahwa jawaban ini salah - bidang tidak perlu bersifat publik atau memiliki pengambil dan penyetel. Dalam jawaban lain untuk pertanyaan ini, saya memberikan konfigurasi alternatif yang tidak memerlukan perubahan pada struktur data asli menjadi (de) serial.
Programmer Bruce

9
Jawabannya bermanfaat, walaupun tidak 100% tepat benar. Aku lupa menaruh 'publik' di vars-ku, dan ini menunjukkan itu. Terima kasih!
ChrisPhoenix

54

Saya memiliki masalah yang sama dalam kode sumber saya. Saya baru saja menambahkan

pengambil

dan

setter

masalah terpecahkan.


1
Sudah mencoba banyak hal, dan solusinya sesederhana ini .... dan dikatakan cukup jelas: "tidak ada properti yang ditemukan untuk dibuat".
aks

2
@ PhilipRego Dia berarti dia menambahkan pengambil dan penyetel untuk bidang tersebut.
Paul

Saya menggunakan perpustakaan lombok, jadi saya hanya menambahkan anterasi Getter dan Setter. Dan semuanya baik-baik saja. Terima kasih.
Rahmat Hidayat

ya, getter dan setters digunakan untuk serialisasi
Jackson./deserialization

25

Masalah dalam kasus saya adalah Jackson mencoba membuat serial objek kosong tanpa atribut atau metode.

Seperti yang disarankan dalam pengecualian saya menambahkan baris berikut untuk menghindari kegagalan pada kacang kosong:

Untuk Jackson 1.9

myObjectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);

Untuk Jackson 2.X

myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

Anda dapat menemukan contoh sederhana tentang jackson menonaktifkan fail_on_empty_beans


9

Saya memiliki masalah yang sama untuk kelas anak di mana saya memiliki kontrol, objek mapper berada di modul umum dan tidak dapat diakses. Saya memecahkannya dengan menambahkan anotasi ini untuk kelas anak saya yang objeknya akan serial.

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)

7

Jika Anda dapat mengedit kelas yang berisi objek itu, saya biasanya hanya menambahkan anotasi

import com.fasterxml.jackson.annotation.JsonIgnore;

@JsonIgnore 
NonSerializeableClass obj;

2
Kesalahan ini juga muncul ketika kelas Anda memiliki metode dengan nama yang dimulai dengan get ... Misalnya NonSerializableClass getMyNonSerializableObject (). Jackson mencoba membuat cerita bersambung dan gagal. Untuk mengatasi masalah ini cukup tambahkan @JsonIgnore atau ganti nama metode.
Alexey Podlasov

1
Digunakan versi yang lebih lama:org.codehaus.jackson.annotate.JsonIgnore
AlikElzin-kilaka

6

Kesalahan ini juga terjadi jika Anda lupa menambahkan metode .build () ke status pengembalian Anda.

return Response.status(Status.OK);         // fails
return Response.status(Status.OK).build(); // works

Saya mendapatkan kesalahan berikut tanpa metode build ():

org.codehaus.jackson.map.JsonMappingException: No serializer found for class com.sun.jersey.core.spi.factory.ResponseBuilderImpl

4

SpringBoot2.0 , Saya mengatasinya dengan mengikuti kode:

@Bean public ObjectMapper objectMapper() {
 return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);}

1
Anda harus menjaga model Anda memiliki metode pengambil dan penyetel.
Janus

1
Selamat datang di SO! Terima kasih telah berkontribusi. Harap tambahkan penjelasan pada jawaban Anda, jadi jelas apa yang dikerjakan kode, mengapa ia bekerja dan bagaimana ia menjawab pertanyaan OPs.
Max Vollmer

Ini membantu saya! Namun menurut saya, Anda harus menyuntikkan ObjectMapper dari konteks dan mengkonfigurasinya setelah itu daripada membuat yang baru.
RoBeaToZ

3

Untuk aplikasi Oracle Java, tambahkan ini setelah ObjectMapperinstantiation:

mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

2

Saya punya masalah yang sama dengan pemuatan malas melalui objek proxy hibernate. Mengatasinya dengan memberi anotasi pada kelas yang memiliki properti pribadi malas dengan:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

Ini menyelesaikan masalah saya. Bisakah Anda memberi tahu saya apa tepatnya ini?
scarface

2

Masalahnya mungkin karena Anda telah mendeklarasikan variabel sebagai private. Jika Anda mengubahnya kepublic , itu berfungsi.

Pilihan yang lebih baik adalah menggunakan metode pengambil dan penyetel untuk itu.

Ini akan menyelesaikan masalah!


2

Saya menemukan setidaknya tiga cara untuk melakukan ini:

  1. Menambahkan public getters entitas Anda yang ingin Anda buat bersambung;
  2. Tambahkan anotasi di bagian atas entitas, jika Anda tidak mau public getters. Ini akan mengubah default untuk Jackson dari Visbility=DEFAULTmenjadi@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) mana setiap pengubah akses diterima;
  3. Ubah ObjectMapperglobal Anda dengan pengaturan objectMapperInstance.setVisibility(JsonMethod.FIELD, Visibility.ANY);. Ini harus dihindari jika Anda tidak membutuhkan fungsi ini secara global.

Pilih berdasarkan kebutuhan Anda.


2

Berikut adalah tiga opsi:

  1. Data / kelas yang telah diakses harus public
  2. Jika tidak public, tambahkan getter & setter
  3. Atau tambahkan @JsonIgnore("context")

1

Silakan gunakan ini di tingkat kelas untuk kacang:

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})

1

menambahkan setter dan pengambil juga akan menyelesaikan masalah karena sudah diperbaiki untuk saya. Untuk Ex:

public class TestA {
    String SomeString = "asd";

    public String getSomeString () {        return SomeString ;     }

    public void setSomeString (String SS ) {        SomeString = SS ;   } 
}

1

Saya hanya mendapatkan getter, setelah menambahkan setter juga, masalah teratasi.


0

Meskipun saya menambahkan getter dan setter saya mendapatkan kesalahan yang sama. Kemudian saya menemukan bug, yaitu atas saran Sonar saya menyerahkan getter dan setter sebagai dilindungi yang menyebabkan masalah. Setelah saya perbaiki itu berfungsi seperti yang diharapkan.


0

di boot musim semi 2.2.5

setelah menambahkan pengambil dan penyetel

saya menambahkan @JsonIgnore di atas bidang.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.