Memetakan Objek JSON Dinamik dengan Jackson

1. Pengenalan

Bekerja dengan struktur data JSON yang telah ditentukan dengan Jackson sangat mudah. Walau bagaimanapun, kadang-kadang kita perlu menangani objek JSON dinamik , yang mempunyai sifat yang tidak diketahui .

Dalam tutorial ringkas ini, kita akan melihat pelbagai cara pemetaan objek JSON dinamik ke dalam kelas Java.

Perhatikan bahawa dalam semua ujian, kami menganggap bahawa kami mempunyai field objectMapper jenis com.fasterxml.jackson.databind.ObjectMapper .

2. Menggunakan JsonNode

Katakan kita mahu memproses spesifikasi produk di kedai web. Semua produk mempunyai beberapa sifat yang sama, tetapi ada yang lain, yang bergantung pada jenis produk.

Sebagai contoh, kami ingin mengetahui nisbah aspek paparan telefon bimbit, tetapi harta ini tidak masuk akal untuk kasut.

Struktur data kelihatan seperti ini:

{ "name": "Pear yPhone 72", "category": "cellphone", "details": { "displayAspectRatio": "97:3", "audioConnector": "none" } }

Kami menyimpan sifat dinamik dalam objek perincian .

Kami dapat memetakan sifat umum dengan kelas Java berikut:

class Product { String name; String category; // standard getters and setters }

Selain itu, kita memerlukan perwakilan yang sesuai untuk objek perincian . Contohnya, com.fasterxml.jackson.databind.JsonNode dapat mengendalikan kekunci dinamik .

Untuk menggunakannya, kami harus menambahkannya sebagai medan ke kelas Produk kami :

class Product { // common fields JsonNode details; // standard getters and setters }

Akhirnya, kami mengesahkan bahawa ia berfungsi:

String json = ""; Product product = objectMapper.readValue(json, Product.class); assertThat(product.getName()).isEqualTo("Pear yPhone 72"); assertThat(product.getDetails().get("audioConnector").asText()).isEqualTo("none");

Walau bagaimanapun, kami mempunyai masalah dengan penyelesaian ini. Kelas kami bergantung pada perpustakaan Jackson kerana kami mempunyai bidang JsonNode .

3. Menggunakan Peta

Kami dapat menyelesaikan masalah ini dengan menggunakan java.util.Map untuk medan perincian . Lebih tepat lagi, kita harus menggunakan Peta .

Semua yang lain tetap sama:

class Product { // common fields Map details; // standard getters and setters }

Dan kemudian kita dapat mengesahkannya dengan ujian:

String json = ""; Product product = objectMapper.readValue(json, Product.class); assertThat(product.getName()).isEqualTo("Pear yPhone 72"); assertThat(product.getDetails().get("audioConnector")).isEqualTo("none");

4. Menggunakan @JsonAnySetter

Penyelesaian sebelumnya baik apabila objek hanya mengandungi sifat dinamik. Walau bagaimanapun, kadang-kadang kita mempunyai sifat tetap dan dinamik yang dicampurkan dalam satu objek JSON .

Sebagai contoh, kita mungkin perlu meratakan representasi produk kita:

{ "name": "Pear yPhone 72", "category": "cellphone", "displayAspectRatio": "97:3", "audioConnector": "none" }

Kita boleh memperlakukan struktur seperti ini sebagai objek dinamik. Sayangnya, ini bermaksud kita tidak dapat menentukan sifat umum - kita juga harus memperlakukannya secara dinamik.

Sebagai alternatif, kita boleh menggunakan @JsonAnySetter untuk menandakan kaedah untuk mengendalikan harta tambahan yang tidak diketahui . Kaedah sedemikian harus menerima dua hujah: nama dan nilai harta tanah:

class Product { // common fields Map details = new LinkedHashMap(); @JsonAnySetter void setDetail(String key, Object value) { details.put(key, value); } // standard getters and setters }

Perhatikan, bahawa kita harus membuat objek terperinci untuk mengelakkan NullPointerExceptions .

Oleh kerana kami menyimpan sifat dinamik dalam Peta , kami dapat menggunakannya dengan cara yang sama seperti sebelumnya:

String json = ""; Product product = objectMapper.readValue(json, Product.class); assertThat(product.getName()).isEqualTo("Pear yPhone 72"); assertThat(product.getDetails().get("audioConnector")).isEqualTo("none");

5. Membuat Deserializer Custom

Bagi kebanyakan kes, penyelesaian ini berfungsi dengan baik. Namun, kadang-kadang kita memerlukan kawalan yang lebih banyak. Sebagai contoh, kita dapat menyimpan maklumat deserialisasi mengenai objek JSON kita dalam pangkalan data.

Kami dapat menargetkan situasi tersebut dengan deserializer khusus. Oleh kerana ia adalah topik yang rumit, kami membahasnya dalam artikel yang berbeza, Bermula dengan Deserialization Khusus di Jackson.

6. Kesimpulannya

Dalam artikel ini, kami melihat pelbagai cara menangani objek JSON dinamik dengan Jackson.

Seperti biasa, contohnya terdapat di GitHub.