Ubah JSON menjadi Peta Menggunakan Gson

1. Perkenalan

Dalam tutorial singkat ini, kita akan belajar cara mengonversi string JSON ke Peta menggunakan Gson dari Google .

Kita akan melihat tiga pendekatan berbeda untuk mencapai itu dan membahas pro dan kontra mereka - dengan beberapa contoh praktis.

2. Melewati Map.class

Secara umum, Gson menyediakan API berikut di kelas Gson -nya untuk mengonversi string JSON menjadi objek :

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

Dari tanda tangan, sangat jelas bahwa parameter kedua adalah kelas dari objek yang ingin kita parse JSON. Dalam kasus kami, itu harus 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 tebakan terbaik terkait tipe nilai untuk setiap properti.

Misalnya, angka akan dipaksa menjadi Double s, true dan false menjadi Boolean , dan objek menjadi LinkedTreeMap .

Jika ada kunci duplikat, pemaksaan akan gagal dan itu akan memunculkan JsonSyntaxException.

Dan, karena penghapusan jenis, kami juga tidak dapat mengkonfigurasi perilaku pemaksaan ini. Jadi, jika kita perlu menentukan jenis kunci atau nilai, maka kita memerlukan pendekatan yang berbeda.

3. Menggunakan TypeToken

Untuk mengatasi masalah penghapusan jenis untuk jenis generik, Gson memiliki versi API yang kelebihan beban :

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

Kita dapat membuat Peta dengan parameter tipenya menggunakan TypeToken Gson . Kelas TypeToken mengembalikan instance ParameterizedTypeImpl yang mempertahankan jenis kunci dan nilai bahkan saat waktu proses :

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 membangun tipe Map kita sebagai Map , maka parser akan tetap default seperti yang kita lihat di bagian sebelumnya.

Tentu saja, ini masih kembali ke Gson untuk memaksa tipe primitif. Itu, bagaimanapun, dapat disesuaikan juga.

4. Menggunakan Custom JsonDeserializer

Saat kita membutuhkan kontrol yang sangat baik atas konstruksi objek Map kita, kita dapat mengimplementasikan deserializer kustom tipe JsonDeserializer.

Untuk melihat contoh, anggap JSON kita berisi nama karyawan sebagai kunci dan tanggal perekrutan mereka sebagai nilainya. Selanjutnya, anggaplah format tanggal adalah tttt / BB / hh , yang bukan format standar untuk Gson .

Kita dapat mengkonfigurasi Gson untuk mengurai peta kita secara berbeda, 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 terhadap Map tipe target kita > dan buat objek Gson yang disesuaikan .

Ketika kita sebut fromJson API pada ini Gson objek, parser memanggil deserializer kustom dan kembali yang diinginkan Peta contoh:

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 ketika peta kita mungkin berisi nilai-nilai yang heterogen dan kita memiliki gagasan yang adil tentang berapa banyak jenis nilai yang bisa ada di sana.

Untuk mempelajari lebih lanjut tentang deserializer kustom di Gson , silakan kunjungi Gson Deserialization Cookbook.

5. Kesimpulan

Dalam artikel singkat ini, kami mempelajari beberapa cara untuk membuat peta dari string berformat JSON. Dan kami juga membahas kasus penggunaan yang tepat untuk variasi ini.

Kode sumber untuk contoh tersedia di GitHub.