Saya menggunakan API dari aplikasi android saya, dan semua tanggapan JSON seperti ini:
{
'status': 'OK',
'reason': 'Everything was fine',
'content': {
< some data here >
}
Masalahnya adalah bahwa semua POJO saya memiliki status
, reason
bidang, dan di dalam content
bidang tersebut adalah POJO asli yang saya inginkan.
Apakah ada cara untuk membuat konverter khusus Gson untuk selalu mengekstrak content
bidang, jadi retrofit mengembalikan POJO yang sesuai?
Jawaban:
Anda akan menulis deserializer khusus yang mengembalikan objek yang disematkan.
Misalkan JSON Anda adalah:
Anda kemudian akan memiliki
Content
POJO:Kemudian Anda menulis deserializer:
Sekarang jika Anda membuat
Gson
denganGsonBuilder
dan mendaftarkan deserializer:Anda dapat menghapus derialisasi JSON langsung ke
Content
:Edit untuk menambahkan dari komentar:
Jika Anda memiliki jenis pesan yang berbeda tetapi semuanya memiliki kolom "konten", Anda dapat membuat Deserializer generik dengan melakukan:
Anda hanya perlu mendaftarkan sebuah instance untuk setiap tipe Anda:
Ketika Anda memanggil
.fromJson()
tipe dibawa ke deserializer, jadi itu harus bekerja untuk semua tipe Anda.Dan terakhir saat membuat instance Retrofit:
sumber
setConverter(new GsonConverter(gson))
diRestAdapter.Builder
kelas RetrofitPerson.class
danList<Person>.class
/Person[].class
dengan Deserializer terpisah?Solusi @ BrianRoach adalah solusi yang tepat. Perlu dicatat bahwa dalam kasus khusus di mana Anda memiliki objek kustom bersarang bahwa kedua kebutuhan kustom
TypeAdapter
, Anda harus mendaftarkanTypeAdapter
dengan contoh baru dari Gson , jika keduaTypeAdapter
tidak akan pernah disebut. Ini karena kami membuatGson
instance baru di dalam deserializer kustom kami.Misalnya, jika Anda memiliki json berikut:
Dan Anda ingin JSON ini dipetakan ke objek berikut:
Anda akan perlu untuk mendaftarkan
SubContent
'sTypeAdapter
. Agar lebih kuat, Anda bisa melakukan hal berikut:dan kemudian buat seperti ini:
Ini dapat dengan mudah digunakan untuk kasus "konten" bertingkat juga dengan hanya meneruskan contoh baru
MyDeserializer
dengan nilai null.sumber
java.lang.reflect.Type
Agak terlambat tapi semoga ini bisa membantu seseorang.
Cukup buat TypeAdapterFactory berikut.
dan tambahkan ke pembuat GSON Anda:
atau
sumber
jsonElement
?. seperti yang saya milikicontent
,content1
dll.Mengalami masalah yang sama beberapa hari lalu. Saya telah menyelesaikan ini menggunakan kelas pembungkus respons dan transformator RxJava, yang menurut saya solusi yang cukup fleksibel:
Pembungkus:
Pengecualian khusus untuk dilempar, ketika status tidak OK:
Trafo Rx:
Contoh penggunaan:
Topik saya: Retrofit 2 RxJava - Gson - Deserialisasi "Global", ubah jenis respons
sumber
Melanjutkan ide Brian, karena kita hampir selalu memiliki banyak resource REST dengan akarnya masing-masing, mungkin berguna untuk menggeneralisasi deserialisasi:
Kemudian untuk mem-parsing sample payload dari atas, kita dapat mendaftarkan deserializer GSON:
sumber
Solusi yang lebih baik bisa jadi ini ..
Kemudian, tentukan layanan Anda seperti ini ..
sumber
Sesuai jawaban @Brian Roach dan @rafakob saya melakukan ini dengan cara berikut
Tanggapan Json dari server
Kelas penangan data umum
Serializer khusus
Objek Gson
Panggilan api
sumber
Ini adalah solusi yang sama dengan @AYarulin tetapi anggaplah nama kelasnya adalah nama kunci JSON. Dengan cara ini Anda hanya perlu memasukkan nama Kelas.
Kemudian untuk mengurai sample payload dari atas, kita bisa melakukan registrasi deserializer GSON. Ini bermasalah karena Kunci peka huruf besar / kecil, jadi huruf besar-kecil nama kelas harus cocok dengan huruf besar / kecil dari kunci JSON.
sumber
Berikut versi Kotlin berdasarkan jawaban Brian Roach dan AYarulin.
sumber
Dalam kasus saya, kunci "konten" akan berubah untuk setiap respons. Contoh:
Dalam kasus seperti itu saya menggunakan solusi serupa seperti yang tercantum di atas tetapi harus mengubahnya. Anda dapat melihat intinya di sini . Agak terlalu besar untuk diposting di sini di SOF.
Anotasi
@InnerKey("content")
digunakan dan kode lainnya adalah untuk memfasilitasi penggunaannya dengan Gson.sumber
Jangan lupa
@SerializedName
dan@Expose
anotasi untuk semua anggota Kelas dan anggota Kelas Dalam yang paling banyak dipisahkan dari JSON oleh GSON.Lihat https://stackoverflow.com/a/40239512/1676736
sumber
Solusi sederhana lainnya:
sumber