Tukarkan JSON ke Peta Menggunakan Gson

1. Pengenalan

Dalam tutorial ringkas ini, kita akan belajar bagaimana mengubah rentetan JSON ke Peta menggunakan Gson dari Google .

Kami akan melihat tiga pendekatan berbeza untuk mencapainya dan membincangkan kebaikan dan keburukan mereka - dengan beberapa contoh praktikal.

2. Melewati Peta.kelas

Secara umum, Gson menyediakan API berikut dalam kelas Gson untuk menukar rentetan JSON ke objek :

public  T fromJson(String json, Class classOfT) throws JsonSyntaxException;

Dari tandatangan, sangat jelas bahawa parameter kedua adalah kelas objek yang kami maksudkan untuk dihuraikan oleh JSON. Dalam kes kami, mestilah Map.class :

String jsonString = "{'employee.name':'Bob','employee.salary':10000}"; Gson gson = new Gson(); Map map = gson.fromJson(jsonString, Map.class); Assert.assertEquals(2, map.size()); Assert.assertEquals(Double.class, map.get("employee.salary").getClass());

Pendekatan ini akan membuat tekaan terbaik mengenai jenis nilai bagi setiap harta tanah.

Contohnya, nombor akan dipaksakan menjadi Double s, true dan false menjadi Boolean , dan objek ke LinkedTreeMap s.

Sekiranya ada kunci pendua, paksaan akan gagal dan ia akan membuang JsonSyntaxException.

Oleh kerana penghapusan jenis, kami juga tidak akan dapat mengatur kelakuan paksaan ini. Jadi, jika kita perlu menentukan jenis kunci atau nilai, maka kita memerlukan pendekatan yang berbeza.

3. Menggunakan TypeToken

Untuk mengatasi masalah penghapusan jenis untuk jenis generik, Gson mempunyai versi API yang terlalu banyak :

public  T fromJson(String json, Type typeOfT) throws JsonSyntaxException;

Kami boleh membina Peta dengan parameter jenisnya menggunakan TypeToken Gson . The TypeToken pulangan kelas satu contoh ParameterizedTypeImpl yang mengekalkan jenis kunci dan nilai walaupun pada masa berjalan :

String jsonString = "{'Bob' : {'name': 'Bob Willis'}," + "'Jenny' : {'name': 'Jenny McCarthy'}, " + "'Steve' : {'name': 'Steven Waugh'}}"; Gson gson = new Gson(); Type empMapType = new TypeToken() {}.getType(); Map nameEmployeeMap = gson.fromJson(jsonString, empMapType); Assert.assertEquals(3, nameEmployeeMap.size()); Assert.assertEquals(Employee.class, nameEmployeeMap.get("Bob").getClass()); 

Sekarang, jika kita membina jenis Peta kita sebagai Peta , maka pengurai akan tetap lalai seperti yang kita lihat di bahagian sebelumnya.

Sudah tentu, ini masih berlaku kepada Gson kerana memaksa jenis primitif. Namun, itu juga dapat disesuaikan.

4. Menggunakan Custom JsonDeserializer

Apabila kita memerlukan kawalan yang terperinci terhadap pembinaan objek Peta kita, kita dapat menerapkan deserializer khas JsonDeserializer jenis .

Untuk melihat contohnya, anggap JSON kami mengandungi nama pekerja sebagai kunci dan tarikh pengambilan mereka sebagai nilainya. Selanjutnya, anggap format tarikh adalah yyyy / MM / dd , yang bukan format standard untuk Gson .

Kita boleh mengkonfigurasi Gson untuk menguraikan peta kita secara berbeza, kemudian, dengan menerapkan JsonDeserializer:

public class StringDateMapDeserializer implements JsonDeserializer { private SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd"); @Override public Map deserialize(JsonElement elem, Type type, JsonDeserializationContext jsonDeserializationContext) { return elem.getAsJsonObject() .entrySet() .stream() .filter(e -> e.getValue().isJsonPrimitive()) .filter(e -> e.getValue().getAsJsonPrimitive().isString()) .collect( Collectors.toMap( Map.Entry::getKey, e -> formatDate(e.getValue()))); } private Date formatDate(Object value) { try { return format(value.getAsString()); } catch (ParseException ex) { throw new JsonParseException(ex); } } } 

Sekarang, kita harus mendaftarkannya di GsonBuilder dengan jenis peta sasaran kita > dan membina objek Gson yang disesuaikan .

Apabila kita memanggil API dariJson pada objek Gson ini, pengurai memanggil deserializer kustom dan mengembalikan contoh Peta yang diinginkan :

String jsonString = "{'Bob': '2017-06-01', 'Jennie':'2015-01-03'}"; Type type = new TypeToken(){}.getType(); Gson gson = new GsonBuilder() .registerTypeAdapter(type, new StringDateMapDeserializer()) .create(); Map empJoiningDateMap = gson.fromJson(jsonString, type); Assert.assertEquals(2, empJoiningDateMap.size()); Assert.assertEquals(Date.class, empJoiningDateMap.get("Bob").getClass()); 

Taktik ini juga berguna apabila peta kita mungkin mengandungi nilai-nilai heterogen dan kita mempunyai idea yang adil tentang berapa banyak jenis nilai yang ada.

Untuk mengetahui lebih lanjut mengenai deserializer khusus di Gson , jangan ragu untuk membaca Buku Panduan Deserialization Gson.

5. Kesimpulan

Dalam artikel pendek ini, kami mempelajari beberapa cara untuk membina peta dari rentetan berformat JSON. Dan kami juga membincangkan kes penggunaan yang betul untuk variasi ini.

Kod sumber untuk contoh boleh didapati di GitHub.