Java XML dan JSON: Pemprosesan dokumen untuk Java SE, Bahagian 2: JSON-B

Dalam artikel ini, kami akan terus meneroka XML dan JSON di Java 11 dan seterusnya.

Contoh dalam artikel ini akan memperkenalkan anda kepada JSON-B, JSON Binding API untuk Java. Setelah ikhtisar ringkas dan arahan pemasangan, saya akan menunjukkan kepada anda cara menggunakan JSON-B untuk membuat siri dan deserialisasi objek, susunan, dan koleksi Java; cara menyesuaikan siri dan deserialisasi menggunakan JSON-B; dan bagaimana menggunakan penyesuai JSON-B untuk menukar objek sumber menjadi objek sasaran semasa bersiri atau deserialisasi.

Bahan untuk artikel ini benar-benar baru, tetapi dapat dianggap sebagai bab tambahan (Bab 13) untuk buku baru saya, yang baru-baru ini diterbitkan oleh Apress: Java XML dan JSON, Edisi Kedua .

Mengenai buku: Java XML dan JSON

Seperti yang saya kongsikan dalam artikel saya sebelumnya, Apress baru saja menerbitkan edisi kedua buku saya, Java XML dan JSON . Dengan senang hati menulis keseluruhan buku mengenai XML dan JSON, dua teknologi yang saya anggap lebih lengkap daripada kompetitif. Setelah buku itu diterbitkan, saya menambahkan contoh baru untuk Bab 6: Mengubah dokumen XML dengan XSLT, dan untuk Bab 11: Memproses JSON dengan Jackson. Artikel terakhir saya, "Java XML dan JSON: Pemprosesan dokumen untuk Java SE, Bahagian 1" memperkenalkan pelbagai teknik transformasi dan pemprosesan dokumen menggunakan SAXON dan Jackson. Pastikan anda membaca artikel itu untuk mengetahui lebih lanjut mengenai teknik ini.

Dapatkan kodnya

Muat turun kod sumber untuk contoh yang digunakan dalam tutorial ini.

Apa itu JSON-B?

JSON-B adalah lapisan pengikat standard dan API untuk menukar objek Java ke dan dari dokumen JSON. Ini mirip dengan Java Architecture for XML Binding (JAXB), yang digunakan untuk mengubah objek Java ke dan dari XML.

JSON-B dibina di atas JSON-P, JSON Processing API yang digunakan untuk menghurai, membuat, membuat pertanyaan, dan mengubah dokumen JSON. JSON-B diperkenalkan oleh Java Specification Request (JSR) 367 lebih dari setahun setelah pelepasan terakhir JSR 353, JSR untuk JSON-P.

API JSON-B

Laman web Java API for JSON Binding (JSON-B) memperkenalkan JSON-B dan menyediakan akses ke pelbagai sumber, termasuk dokumentasi API. Menurut dokumentasi, modul JSON-B menyimpan enam pakej:

  • javax.json.bind: Menentukan titik masuk untuk mengikat objek Java ke dokumen JSON.
  • javax.json.bind.adapter: Mentakrifkan kelas yang berkaitan dengan penyesuai.
  • javax.json.bind.annotation: Mendefinisikan anotasi untuk menyesuaikan pemetaan antara elemen program Java dan dokumen JSON.
  • javax.json.bind.config: Mendefinisikan strategi dan kebijakan untuk menyesuaikan pemetaan antara elemen program Java dan dokumen JSON.
  • javax.json.bind.serializer: Mendefinisikan antara muka untuk membuat serializer dan deserializer khas.
  • javax.json.bind.spi: Menentukan Antaramuka Penyedia Perkhidmatan (SPI) untuk memasukkan JsonbBuilders.

Laman web JSON-B juga menyediakan pautan ke Yasson, kerangka kerja Java yang menyediakan lapisan pengikat standard antara kelas Java dan dokumen JSON, dan pelaksanaan rujukan rasmi API JSON Binding.

JSON-B dan Java EE 8

Seperti JSON-P, JSON-B pada awalnya dipertimbangkan untuk dimasukkan dalam Java SE, tetapi dimasukkan dalam rilis Java EE 8 sebagai gantinya. Anda masih boleh bekerja dengan JSON-B dalam konteks Java SE.

Muat turun dan pasang JSON-B

JSON-B 1.0 adalah versi semasa pada masa penulisan. Anda boleh mendapatkan pelaksanaan rujukan Yasson dari perpustakaan ini dari repositori Maven. Anda perlu memuat turun fail JAR berikut:

  • Javax JSON Bind API 1.0: Mengandungi semua classfile JSON-B. Saya memuat turun javax.json.bind-api-1.0.jar.
  • Yasson: Mengandungi pelaksanaan rujukan Eclipse JSON-B. Saya memuat turun yasson-1.0.3.jar.
  • JSR 374 (JSON Processing) Default Provider: Mengandungi semua classfile JSON-P 1.0 bersama dengan classfile penyedia lalai Glassfish. Saya memuat turun javax.json-1.1.4.jar.

Tambahkan fail JAR ini ke classpath anda semasa menyusun dan menjalankan kod yang menggunakan perpustakaan ini:

javac -cp javax.json.bind-api-1.0.jar;. main source file java -cp javax.json.bind-api-1.0.jar;yasson-1.0.3.jar;javax.json-1.1.4.jar;. main classfile

Serialisasi dan deserialisasi objek Java dengan JSON-B

The javax.json.bindpakej yang disediakan Jsonbdan JsonbBuilderantara muka, yang bertindak sebagai Entrypoint ke perpustakaan ini:

  • Jsonbmenyediakan toJson()kaedah yang terlalu banyak untuk menyusun pokok objek Java ke dokumen JSON, dan fromJson()kaedah untuk deserialisasi dokumen JSON ke pohon objek Java.
  • JsonbBuildermenyediakan newBuilder()dan kaedah lain untuk mendapatkan pembangun baru, build()dan create()kaedah untuk mengembalikan Jsonbobjek baru .

Contoh kod berikut menunjukkan penggunaan asas Jsonbdan JsonBuilderjenis:

// Create a new Jsonb instance using the default JsonbBuilder implementation. Jsonb jsonb = JsonbBuilder.create(); // Create an Employee object from a hypothetical Employee class. Employee employee = ... // Convert the Employee object to a JSON document stored in a string. String jsonEmployee = jsonb.toJson(employee); // Convert the previously-created JSON document to an Employee object. Employee employee2 = jsonb.fromJson(jsonEmployee, Employee.class);

Contoh ini menyembah sesuatu Jsonb's String toJson(Object object)kaedah untuk cerita bersambung objek Java, ( Employee). Kaedah ini diteruskan akar pohon objek Java untuk bersiri. Sekiranya nulldilalui, toJson()lontar java.lang.NullPointerException. Ia melontar javax.json.bind.JsonbExceptionapabila masalah yang tidak dijangka (seperti ralat I / O) berlaku semasa bersiri.

Ini serpihan kod juga menyembah Jsonb's T fromJson(String str, Class type)kaedah generik, yang digunakan untuk deserialization. Kaedah ini diteruskan dokumen JSON berdasarkan rentetan untuk deserialisasi dan jenis akar akar pohon objek Java yang dihasilkan, yang dikembalikan. Kaedah ini membuang NullPointerExceptionbila nullditeruskan ke salah satu parameter; ia melontarkan JsonbExceptionapabila masalah yang tidak dijangka berlaku semasa deserialisasi.

Saya memetik fragmen kod dari JSONBDemoaplikasi yang menyediakan demonstrasi asas JSON-B. Penyenaraian 1 menunjukkan kod sumber untuk demo ini.

Penyenaraian 1. JSONBDemo.java (versi 1)

import java.time.LocalDate; import javax.json.bind.Jsonb; import javax.json.bind.JsonbBuilder; public class JSONBDemo { public static void main(String[] args) { Jsonb jsonb = JsonbBuilder.create(); Employee employee = new Employee("John", "Doe", 123456789, false, LocalDate.of(1980, 12, 23), LocalDate.of(2002, 8, 14)); String jsonEmployee = jsonb.toJson(employee); System.out.println(jsonEmployee); System.out.println(); Employee employee2 = jsonb.fromJson(jsonEmployee, Employee.class); System.out.println(employee2); } }

main()pertama membuat Jsonbobjek diikuti dengan Employeeobjek. Ia kemudian memanggil toJson()untuk membuat siri Employeeobjek ke dokumen JSON yang disimpan dalam rentetan. Selepas percetakan dokumen ini, main()menyembah sesuatu fromJson()dengan tali sebelumnya dan Employee's java.lang.Classobjek untuk deserialize dokumen JSON yang lain Employeeobjek, yang kemudiannya dicetak.

Penyenaraian 2 menyajikan Employeekod sumber.

Penyenaraian 2. Employee.java (versi 1)

import java.time.LocalDate; public class Employee { private String firstName; private String lastName; private int ssn; private boolean isMarried; private LocalDate birthDate; private LocalDate hireDate; private StringBuffer sb = new StringBuffer(); public Employee() {} public Employee(String firstName, String lastName, int ssn, boolean isMarried, LocalDate birthDate, LocalDate hireDate) { this.firstName = firstName; this.lastName = lastName; this.ssn = ssn; this.isMarried = isMarried; this.birthDate = birthDate; this.hireDate = hireDate; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public int getSSN() { return ssn; } public boolean isMarried() { return isMarried; } public LocalDate getBirthDate() { return birthDate; } public LocalDate getHireDate() { return hireDate; } public void setFirstName(String firstName) { this.firstName = firstName; } public void setLastName(String lastName) { this.lastName = lastName; } public void setSSN(int ssn) { this.ssn = ssn; } public void setIsMarried(boolean isMarried) { this.isMarried = isMarried; } public void setBirthDate(LocalDate birthDate) { this.birthDate = birthDate; } public void setHireDate(LocalDate hireDate) { this.hireDate = hireDate; } @Override public String toString() { sb.setLength(0); sb.append("First name ["); sb.append(firstName); sb.append("], Last name ["); sb.append(lastName); sb.append("], SSN ["); sb.append(ssn); sb.append("], Married ["); sb.append(isMarried); sb.append("], Birthdate ["); sb.append(birthDate); sb.append("], Hiredate ["); sb.append(hireDate); sb.append("]"); return sb.toString(); } }

Susun Senarai 1 dan 2 seperti berikut:

javac -cp javax.json.bind-api-1.0.jar;. JSONBDemo.java

Jalankan aplikasi seperti berikut:

java -cp javax.json.bind-api-1.0.jar;yasson-1.0.3.jar;javax.json-1.1.4.jar;. JSONBDemo

You should observe the following output (spread across multiple lines for readability):

{"SSN":123456789,"birthDate":"1980-12-23","firstName":"John","hireDate":"2002-08-14", "lastName":"Doe","married":false} First name [John], Last name [Doe], SSN [123456789], Married [false], Birthdate [1980-12-23], Hiredate [2002-08-14] 

Rules for working with JSON-B

While playing with this application, I observed some interesting behaviors that led me to formulate the following rules concerning Employee:

  • The class must be public; otherwise, an exception is thrown.
  • toJson() will not serialize fields with non-public getter methods.
  • fromJson() will not deserialize fields with non-public setter methods.
  • fromJson() throws JsonbException in the absence of a public noargument constructor.

In order to seamlessly convert between Java object fields and JSON data, JSON-B has to support various Java types. For example, JSON-B supports the following basic Java types:

  • java.lang.Boolean
  • java.lang.Byte
  • java.lang.Character
  • java.lang.Double
  • java.lang.Float
  • java.lang.Integer
  • java.lang.Long
  • java.lang.Short
  • java.lang.String

Jenis tambahan seperti java.math.BigInteger, java.util.Datedan java.time.LocalDatedisokong. Lihat spesifikasi JSON-B untuk senarai lengkap jenis yang disokong.

Susun dan susun atur susunan dan koleksi dengan JSON-B

Bahagian sebelumnya memfokuskan pada siri dan deserialisasi objek Java tunggal. JSON-B juga menyokong keupayaan untuk membuat siri dan mendeserisasi susunan dan koleksi objek. Penyenaraian 3 memberikan demonstrasi.

Penyenaraian 3. JSONBDemo.java (versi 2)

import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.json.bind.Jsonb; import javax.json.bind.JsonbBuilder; public class JSONBDemo { public static void main(String[] args) { arrayDemo(); listDemo(); } // Serialize and deserialize an array of Employee objects. static void arrayDemo() { Jsonb jsonb = JsonbBuilder.create(); Employee[] employees = { new Employee("John", "Doe", 123456789, false, LocalDate.of(1980, 12, 23), LocalDate.of(2002, 8, 14)), new Employee("Jane", "Smith", 987654321, true, LocalDate.of(1982, 6, 13), LocalDate.of(2001, 2, 9)) }; String jsonEmployees = jsonb.toJson(employees); System.out.println(jsonEmployees); System.out.println(); employees = null; employees = jsonb.fromJson(jsonEmployees, Employee[].class); for (Employee employee: employees) { System.out.println(employee); System.out.println(); } } // Serialize and deserialize a List of Employee objects. static void listDemo() { Jsonb jsonb = JsonbBuilder.create(); List employees = Arrays.asList(new Employee("John", "Doe", 123456789, false, LocalDate.of(1980, 12, 23), LocalDate.of(2002, 8, 14)), new Employee("Jane", "Smith", 987654321, true, LocalDate.of(1982, 6, 13), LocalDate.of(1999, 7, 20))); String jsonEmployees = jsonb.toJson(employees); System.out.println(jsonEmployees); System.out.println(); employees = null; employees = jsonb.fromJson(jsonEmployees, new ArrayList(){}. getClass().getGenericSuperclass()); System.out.println(employees); } }

Penyenaraian 3 adalah peluasan ringkas Penyenaraian 1, dan menggunakan Employeekelas yang sama yang ditunjukkan dalam Penyenaraian 2. Selain itu, contoh kod ini memanggil kaedah toJson()dan fromJson()kaedah yang sama .