Saya ingin mentransfer objek daftar melalui Google Gson, tetapi saya tidak tahu bagaimana cara deserialisasi tipe generik.
Apa yang saya coba setelah melihat ini (jawaban BalusC):
MyClass mc = new Gson().fromJson(result, new List<MyClass>(){}.getClass());
tapi kemudian saya mendapatkan kesalahan dalam gerhana mengatakan "Jenis Daftar baru () {} harus menerapkan metode abstrak yang diwarisi ..." dan jika saya menggunakan perbaikan cepat saya mendapatkan monster lebih dari 20 metode bertopik.
Saya cukup yakin bahwa ada solusi yang lebih mudah, tetapi sepertinya saya tidak dapat menemukannya!
Edit:
Sekarang sudah
Type listType = new TypeToken<List<MyClass>>()
{
}.getType();
MyClass mc = new Gson().fromJson(result, listType);
Namun, saya mendapatkan pengecualian berikut di baris "fromJson":
java.lang.NullPointerException
at org.apache.harmony.luni.lang.reflect.ListOfTypes.length(ListOfTypes.java:47)
at org.apache.harmony.luni.lang.reflect.ImplForType.toString(ImplForType.java:83)
at java.lang.StringBuilder.append(StringBuilder.java:203)
at com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:56)
at com.google.gson.JsonDeserializationVisitor.invokeCustomDeserializer(JsonDeserializationVisitor.java:88)
at com.google.gson.JsonDeserializationVisitor.visitUsingCustomHandler(JsonDeserializationVisitor.java:76)
at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:106)
at com.google.gson.JsonDeserializationContextDefault.fromJsonArray(JsonDeserializationContextDefault.java:64)
at com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:49)
at com.google.gson.Gson.fromJson(Gson.java:568)
at com.google.gson.Gson.fromJson(Gson.java:515)
at com.google.gson.Gson.fromJson(Gson.java:484)
at com.google.gson.Gson.fromJson(Gson.java:434)
Saya lakukan JsonParseExceptions menangkap dan "hasil" tidak null.
Saya memeriksa listType dengan debugger dan mendapatkan yang berikut:
- Jenis daftar
- args = ListOfTypes
- daftar = nol
- resolvedTypes = Jenis [1]
- loader = PathClassLoader
- ownerType0 = null
- ownerTypeRes = null
- rawType = Kelas (java.util.ArrayList)
- rawTypeName = "java.util.ArrayList"
- args = ListOfTypes
jadi sepertinya doa "getClass" tidak berfungsi dengan baik. Ada saran ...?
Sunting2: Saya sudah memeriksa pada Panduan Pengguna Gson . Itu menyebutkan Pengecualian Runtime yang harus terjadi selama parsing tipe generik ke Json. Saya melakukannya "salah" (tidak ditampilkan di atas), seperti pada contoh, tetapi tidak mendapatkan pengecualian sama sekali. Jadi saya mengubah serialisasi seperti dalam panduan pengguna yang disarankan. Tapi itu tidak membantu.
Sunting3: Dipecahkan, lihat jawaban saya di bawah ini.
TokenType
. Sudahkah Anda mencobanya?Jawaban:
Metode deserialize koleksi generik:
Karena beberapa orang di komentar telah menyebutkannya, inilah penjelasan tentang bagaimana
TypeToken
kelas digunakan. Konstruksinew TypeToken<...>() {}.getType()
menangkap tipe waktu kompilasi (antara<
dan>
) kejava.lang.reflect.Type
objek runtime . Tidak sepertiClass
objek, yang hanya bisa mewakili tipe mentah (terhapus), theType
objek dapat mewakili tipe apa pun dalam bahasa Java, termasuk instantiasi parameterized dari tipe generik.The
TypeToken
kelas itu sendiri tidak memiliki konstruktor publik, karena Anda tidak seharusnya untuk membangun itu secara langsung. Sebaliknya, Anda selalu membuat subclass anonim (karenanya{}
, yang merupakan bagian penting dari ungkapan ini).Karena penghapusan tipe,
TypeToken
kelas hanya dapat menangkap tipe yang sepenuhnya diketahui pada waktu kompilasi. (Yaitu, Anda tidak dapat melakukannew TypeToken<List<T>>() {}.getType()
untuk parameter tipeT
.)Untuk informasi lebih lanjut, lihat dokumentasi untuk
TypeToken
kelas .sumber
{ "myObjectArray":[ {....} , {....} , {....} ] }
, saya telah membuat file model untuk{....}
, bagaimana cara mendapatkan kode koleksi umum ini untuk tidak menganggap elemen root saya adalah array tanpa membuat file objek bersarang baruCara lain adalah dengan menggunakan array sebagai tipe, misalnya:
Dengan cara ini Anda menghindari semua kerumitan dengan objek Type, dan jika Anda benar-benar membutuhkan daftar, Anda selalu dapat mengubah array menjadi daftar dengan:
IMHO ini jauh lebih mudah dibaca.
Dan untuk membuatnya menjadi daftar aktual (yang dapat dimodifikasi, lihat batasan
Arrays.asList()
) maka lakukan saja hal berikut:sumber
MyClass
nilainya dan itu akan didefinisikan secara dinamis!T[] yourClassList = gson.fromJson(message, T[].class);
// tidak dapat memilih dari variabel tipemcList
dalam jawaban ini hanya hasil dari panggilan untukArrays.asList
. Metode ini mengembalikan daftar yang sebagian besar jika tidak semua metode opsional dibiarkan tidak diterapkan dan melempar pengecualian. Misalnya, Anda tidak dapat menambahkan elemen apa pun ke daftar itu. Seperti yang diedit kemudian,Arrays.asList
memiliki keterbatasan, dan membungkusnya menjadi aktualArrayList
memungkinkan Anda untuk mendapatkan daftar yang lebih berguna dalam banyak kasus.Array.newInstance(clazz, 0).getClass()
seperti yang dijelaskan dalam jawaban David Wood .Lihat posting ini. Java Type Generic sebagai Argumen untuk GSON
Saya punya solusi yang lebih baik untuk ini. Inilah kelas pembungkus untuk daftar sehingga pembungkus dapat menyimpan jenis daftar yang tepat.
Dan kemudian, kodenya bisa sederhana:
sumber
mEntity.rulePattern
?Karena
Gson 2.8
, kita dapat membuat fungsi util sepertiContoh menggunakan
sumber
TypeToken#getParameterized
terlihat jauh lebih baik daripada hack dengan subclass anonimWep, cara lain untuk mencapai hasil yang sama. Kami menggunakannya untuk keterbacaannya.
Alih-alih melakukan kalimat yang sulit dibaca ini:
Buat kelas kosong yang memperluas Daftar objek Anda:
Dan gunakan saat mem-parsing JSON:
sumber
Untuk Kotlin secara sederhana:
atau, inilah fungsi yang bermanfaat:
Lalu, untuk menggunakan:
sumber
inline fun <reified T> buildType() = object : TypeToken<T>() {}.type!!
dan menyebutnya dengan tipe List:buildType<List<YourMagicObject>>()
buildType
dan juga memanggil fungsi dengan tipe generik? Apakah ini salah cetak? - Ini akan membuat ArrayList <ArrayList <YourMagicObject>>Contoh:
sumber
DevNG
jawaban di atas, ditulis 2 tahun sebelumnya: stackoverflow.com/a/17300003/1339923 (dan bacalah jawaban itu untuk peringatan untuk pendekatan ini)Saat menjawab pertanyaan awal saya, saya telah menerima jawaban doc_180, tetapi jika seseorang menghadapi masalah ini lagi, saya akan menjawab bagian kedua dari pertanyaan saya juga:
NullPointerError yang saya jelaskan tidak ada hubungannya dengan Daftar itu sendiri, tetapi dengan kontennya!
Kelas "MyClass" tidak memiliki konstruktor "no args", dan tidak ada yang memiliki kelas superclass. Setelah saya menambahkan konstruktor "MyClass ()" sederhana ke MyClass dan superclass-nya, semuanya bekerja dengan baik, termasuk serialisasi daftar dan deserialisasi seperti yang disarankan oleh doc_180.
sumber
Berikut adalah solusi yang bekerja dengan tipe yang ditentukan secara dinamis. Caranya adalah menciptakan jenis array yang tepat menggunakan Array.newInstance ().
sumber
class.cast()
menghindari peringatan yang tidak dicentang yang disebabkan oleh casting to(T)
. Atau, lebih baik lagi, jangan repot-repot casting dan gunakan sesuatu sepertiArrays.asList()
untuk mengkonversi dari array keList<T>
. Juga, tidak perlu melewati panjang keArray.newInstance()
- array ukuran nol akan cukup baik untuk dipanggilgetClass()
.Saya ingin menambahkan satu kemungkinan lagi. Jika Anda tidak ingin menggunakan TypeToken dan ingin mengonversi array objek json ke ArrayList, maka Anda dapat melanjutkan seperti ini:
Jika struktur json Anda seperti:
}
dan struktur kelas Anda seperti:
maka Anda dapat menguraikannya seperti:
Sekarang Anda dapat mengakses setiap elemen objek className.
sumber
Lihat contoh 2 untuk pemahaman kelas 'Jenis' tentang Gson.
Contoh 1: Dalam deserilizeResturant ini kami menggunakan larik Karyawan [] dan mendapatkan detailnya
Contoh 2:
sumber
Saya menyukai jawaban dari kays1 tetapi saya tidak bisa menerapkannya. Jadi saya membangun versi saya sendiri menggunakan konsepnya.
Pemakaian:
sumber
Dalam kasus Saya, jawaban uncaught_exceptions tidak berfungsi, saya harus menggunakan
List.class
alih-alihjava.lang.reflect.Type
:sumber