Dalam proses pengembangan web, interaksi data sangat diperlukan, yang membutuhkan format data interaktif yang relevan untuk ditentukan sehingga data dapat dilewati antara klien dan server. Biasanya ada dua jenis format data: 1. XML; 2. Json. Secara umum, JSON digunakan untuk meneruskan data. Artikel ini memperkenalkan beberapa masalah yang dihadapi ketika mengkonversi JSON dan objek di Java dan saran terkait.
Pertama, kami memiliki dua konsep untuk JSON:
JSON Object (Notasi Objek JavaScript, Notasi Objek JavaScript). Ini tampaknya merupakan bit JavaScript khusus, tetapi spesifik bahasa dan platform sebagai sintaks. Ini hanya berarti bahwa secara normal ketika kami meneruskan data ke sisi server (browser) kami menggunakan format JSON, dan format ini digunakan untuk mewakili objek JavaScript. Ini terdiri dari serangkaian "nilai kunci", seperti {"id": 1, "name": "Kevin"}, yang agak mirip dengan cara peta pasangan nilai kunci disimpan. Objek JSON yang dijelaskan dalam Java sebenarnya mengacu pada kelas JSONObject, yang biasanya dinamai sesuai nama ini di setiap paket JSONJAR pihak ketiga. Paket toples yang berbeda memiliki implementasi internal yang sedikit berbeda.
String json. Konversi antara objek JSON dan string JSON adalah proses serialisasi dan deserialisasi, yang seperti serialisasi dan deserialisasi objek Java. Transmisi data dalam jaringan dilakukan melalui string, atau aliran biner, dll. Artinya, ketika klien (browser) perlu meneruskan data dalam format JSON, string dilewatkan pada jaringan pada saat ini, dan sisi server tentu saja akan memiliki string (tipe string) setelah menerima data. Kadang -kadang perlu untuk mengonversi string JSON ke objek JSON dan kemudian melakukan operasi berikutnya (tipe string dikonversi ke tipe JSONObject).
Dua konsep di atas pada dasarnya mengklarifikasi format data JSON, atau juga disebut Sintaks JSON. Ada banyak paket toples untuk JSON di Java. Yang paling "umum digunakan" adalah paket JAR yang disediakan oleh "net.sf.json". Artikel ini akan fokus pada paket pit ini. Meskipun pit, ia memiliki berbagai aplikasi. Faktanya, ada paket JSON lain yang sangat baik untuk kami gunakan, seperti FastJson, yang Alibaba klaim sebagai paket JSON tercepat, Google GSON, dan Jackson. Coba gunakan paket "net.sf.json". Tidak hanya ada jebakan, tetapi juga sangat tua, begitu tua sehingga tidak dapat mengunduh kode sumber dalam ide. Repositori Maven menunjukkan bahwa itu dihentikan dalam versi 2.4 pada tahun 2010. Mari kita bicara tentang dua bug yang sudah saya ketahui tentang "net.sf.json" dan bagaimana kedua bug ini dihasilkan.
Paket Pit JSON di Java - net.sf.json
1. Ketika objek Java mengonversi objek JSON, semua metode yang dimulai dengan GET akan dikonversi.
Apa artinya ini, misalnya, objek Java berikut tersedia.
Paket sfjson; import java.util.list;/*** dibuat oleh Kevin pada 2017/12/1. */siswa kelas publik {private int id; Daftar Pribadi <long> kursus; publik int getId () {return id; } public void setid (int id) {this.id = id; } Daftar Publik <long> getCourseIds () {return courseIds; } public void setCourseIdsIds (daftar <long> courseIds) {this.courseids = CourseIds; } public String getSQL () {// Metode untuk mendapatkan pernyataan SQL di kelas ini tidak memiliki pengembalian bidang atribut yang sesuai "Ini adalah SQL."; }}Ketika kami mengonversi objek siswa ke objek JSON, kami berharap format JSON yang dikonversi harus:
{"id": 1, "courseids": [1, 2, 3]}Namun, hasilnya setelah konversi jsonObject json = jsonObject.fromObject (siswa); API adalah:
Dengan kata lain, dapat ditebak bahwa "net.sf.json" mendapatkan metode yang dimulai dengan pengubah publik masuk dalam objek Java, dan mendefinisikan akhirannya sebagai "kunci" objek JSON, dan menentukan nilai pengembalian metode yang dimulai dengan GET sebagai "nilai" dari kunci yang sesuai. Perhatikan bahwa itu adalah metode yang dimulai dengan pengubah publik dapatkan, dan memiliki nilai pengembalian.
Saya pikir ini adalah aturan konversi yang tidak masuk akal. Jika saya mendefinisikan metode dalam objek Java, dan hanya karena metode ini dimulai dengan "dapatkan" dan memiliki nilai pengembalian, itu akan diekspos? Atau apakah itu terkena konsol konsol front-end ketika dikembalikan ke klien (browser)? Penulis menetapkan aturan konversi ini. Alasan kasar yang saya pikirkan adalah: karena Anda mendefinisikannya sebagai metode publik dan menamainya, itu sengaja mengekspos metode ini sehingga klien yang menyebutnya memiliki hak untuk mendapatkannya. Tapi saya masih berpikir ini tidak masuk akal, dan bahkan saya mendefinisikannya sebagai bug. Mungkin tidak masuk akal bagi saya untuk mendefinisikan cara ini, karena menurut tes saya yang sebenarnya, tidak hanya paket "net.sf.json" akan dikonversi sesuai dengan aturan ini, tetapi Fastjson dan Jackson juga mengikuti aturan ini, tetapi Google GSON tidak mengonversi objek ke JSON sesuai dengan aturan ini.
Konversikan objek siswa yang dibangun menjadi objek JSON melalui JSONObject JSON = JsonObject.FromObject (siswa); dan siswa seperti yang dijelaskan di atas. Setelah memasukkan metode ini, metode yang kelebihan beban dari Object (Object, JsonConfig) akan terus dipanggil. Dalam metode yang kelebihan beban ini, instanceof akan digunakan untuk menentukan apakah objek objek yang akan dikonversi adalah enumerasi, anotasi dan jenis lainnya. Jenis -jenis khusus ini akan memiliki metode penilaian khusus. Berikut adalah objek Java Pojo biasa, sehingga akan memasukkan _fromObject (objek, jsonconfig), dan akan ada beberapa penilaian dalam metode ini, dan akhirnya, objek JSON dibuat dengan memanggil defaultBeanProcessing. Metode ini adalah kuncinya, dan akan terus mendapatkan "deskriptor properti" melalui metode properti. Bahkan, itu adalah untuk mendapatkan metode dengan GET, yang dienkapsulasi sebagai PropertyDescriptor di sini. Kelas siswa ini akan mendapatkan 4, yaitu: getClass, getid, getCourseIds, getSQL.
Bahkan, PropertyDescriptor dienkapsulasi secara rinci, dan semua metode membaca dan menulis telah ditetapkan.
Misalnya, metode GetSQL ini telah diuraikan ke dalam PropertyDescriptor pada gambar di atas. Berikut ini disaring beberapa metode melalui kelas ini. Misalnya, metode GetClass bukanlah metode di Pojo, sehingga tidak perlu dikonversi menjadi objek JSON. PropertyDescriptor diperoleh melalui beaninfo#getPropertyDescriptors, dan beanInfo diperoleh melalui introspector baru (BeanClass, null, use_all_beaninfo) .getBeanInfo (); Dan akhirnya Anda akan mencapai metode berikut.
private beaninfo getBeanInfo () melempar introspectionException {... MethodDescriptor mds [] = getTargetMethodInfo (); // Metode ini akan menghubungi GetPublicDeclaredMethods. Anda dapat melihat bahwa itu memang mencari metode publik, dan semua metode publik, termasuk Wait dan PropertyDescriptors lainnya PDS [] = getTargetPropertyInfo (); // Saring sesuai dengan aturan tertentu. Aturan penyaringan semuanya ada dalam metode ini, yaitu untuk memilih metode di mana pengubah publik memiliki awalan Get dan nilai pengembalian ...Saya secara singkat menganalisis kode sumber net.sf.json dan menemukan bahwa seperti yang saya kira, kode sumber spesifik relatif besar dan terbatas dalam ruang, dan perlu dilihat dan dilacak sendiri.
2. Saat mengonversi objek Java ke objek JSON, kesalahan konversi akan terjadi pada daftar <long>
Judul tidak dapat dijelaskan dengan jelas dalam satu kalimat, dan saya sangat yakin bahwa masalah ini adalah bug.
Sekarang ada string JSON {"id": 1, "CourseIds": [1,2,3]}, dan perlu dikonversi ke objek siswa yang disebutkan di atas. Ada dua bidang atribut tipe int dan daftar <long> dalam objek siswa, yang berarti bahwa string JSON ini harus dikonversi ke tipe data yang sesuai.
String json = "{/" id/": 1,/" courseids/": [1,2,3]}"; siswa siswa = (siswa) jsonobject.tobean (jsonobject.fromObject (json), student.class); System.out.println (student.getCourseids (). Get (0) longof);Output di atas seharusnya benar, tetapi sayangnya itu salah. Tepatnya, sudah lama pada waktu kompilasi, tetapi bilangan bulat pada waktu lari. Ini harus dikatakan sebagai jebakan, dan tidak satu pun dari tiga paket JSON lainnya yang memiliki kesalahan seperti itu. Jadi saya yakin itu bug. Mari kita lihat bagaimana bug ini terjadi di net.sf.json. Anda juga perlu membandingkan kode sumber sendiri untuk melihatnya. Sementara saya terus memperdalam debug breakpoint, saya menemukan bahwa ketika net.sf.json sedang memproses data integer, saya menemukan metode ini numberutils#createNumber. Kelas ini menilai tipe datanya saat mengekstraksi data dari string. Tujuan asli adalah memproses angka selama jika memiliki "L" atau "L" setelahnya. Dari sudut pandang ini, hasil akhirnya harus benar.
case 'l': case 'l': if (dec == null && exp == null && (numeric.charat (0) == '-' && isDigits (numeric.substring (1)) || isDigits (numeric))) {coba {return createLong (numerik); } catch (NumberFormateException var11) {return createBigInteger (numeric); }} else {throw numberFormateException baru (str + "bukan nomor yang valid."); }Memang, sejauh ini, net.sf.json telah secara akurat menilai tipe data melalui pengidentifikasi setelah angka. Masalahnya terletak pada fakta bahwa setelah memperoleh nilai ini dan tipe datanya, perlu disimpan di JSONObject. Metode jsonutils#transformNumber ada selama proses penyimpanan. Keberadaan metode ini setidaknya murni mewah dalam tampilan saat ini.
Public Static Number TransformNumber (Number Input) {if (input inpoF float) {return new double (input.toString ()); } else if (input instanceof short) {return new integer (input.intvalue ()); } else if (input instanceof byte) {return new integer (input.intvalue ()); } else {if (input inputof long) {long max = new long (2147483647l); if (input.longValue () <= max.longValue () && input.longValue ()> = -2147483648l) {// bahkan jika jenis aslinya panjang, selama berada dalam kisaran integer, pada akhirnya akan dikonversi ke integer. mengembalikan integer baru (input.intvalue ()); }} return input; }}Kode di atas dengan jelas menunjukkan pelakunya, apakah itu tipe panjang (tipe panjang dalam kisaran integer), termasuk byte dan pendek, itu akan dikonversi ke integer. Saya tidak mengerti apa arti kode ini. Jenis data yang akurat harus ditentukan berdasarkan huruf setelah angka, dan tipe data yang akurat harus dikonversi lagi nanti, yang mengarah ke bug yang disebutkan di awal. Masalah ini hampir tidak dapat dihindari, jadi cara terbaik adalah tidak menggunakannya.
Kedua jebakan ini ditemukan secara kebetulan. Disarankan untuk tidak menggunakan paket JSON net.sf.json yang belum dipertahankan. Selain itu, paket net.sf.json tidak begitu ketat dalam verifikasi format JSON. Jika format seperti itu adalah "{" id ": 1," CourseIds ":" [1,2,3] "}", sebuah pengecualian akan dilemparkan ke dalam tiga paket lainnya, tetapi net.sf.json tidak akan.
Artikel di atas membahas jebakan JSON dan transfer objek di Java secara rinci. Ini semua konten yang saya bagikan dengan Anda. Saya harap ini dapat memberi Anda referensi dan saya harap Anda dapat mendukung wulin.com lebih lanjut.