Java XML и JSON: Обработка на документи за Java SE, Част 2: JSON-B

В тази статия ще продължим да изследваме XML и JSON в Java 11 и по-нови версии.

Примерите в тази статия ще ви запознаят с JSON-B, JSON Binding API за Java. След бърз преглед и инструкция за инсталиране, ще ви покажа как да използвате JSON-B за сериализиране и десериализиране на Java обекти, масиви и колекции; как да персонализирате сериализацията и десериализацията с помощта на JSON-B; и как да използваме JSON-B адаптери за конвертиране на обекти на източник в обекти по време на сериализация или десериализация.

Материалът за тази статия е съвсем нов, но може да се счита за допълнителна глава (Глава 13) за новата ми книга, наскоро публикувана от Apress: Java XML и JSON, второ издание .

Относно книгата: Java XML и JSON

Както споделих в предишната си статия, Apress току-що публикува второто издание на моята книга, Java XML и JSON . За мен беше удоволствие да напиша цяла книга за XML и JSON, две технологии, които считам за повече допълващи, отколкото конкурентни. След публикуването на книгата добавих нови примери за Глава 6: Трансформиране на XML документи с XSLT и за Глава 11: Обработка на JSON с Джаксън. Последната ми статия "Java XML и JSON: Обработка на документи за Java SE, част 1" представи разнообразни техники за преобразуване и обработка на документи, използвайки SAXON и Jackson. Не забравяйте да разгледате тази статия, за да научите повече за тези техники.

Вземете кода

Изтеглете изходния код за примери, използвани в този урок.

Какво е JSON-B?

JSON-B е стандартен свързващ слой и API за конвертиране на Java обекти в и от JSON документи. Подобно е на Java Architecture for XML Binding (JAXB), която се използва за конвертиране на Java обекти в и от XML.

JSON-B е изграден върху JSON-P, JSON Processing API, използван за анализиране, генериране, заявки и трансформиране на JSON документи. JSON-B беше въведен от Java Specification Request (JSR) 367 повече от година след окончателното пускане на JSR 353, JSR за JSON-P.

API на JSON-B

Уебсайтът на Java API за обвързване JSON (JSON-B) въвежда JSON-B и осигурява достъп до различни ресурси, включително документация за API. Според документацията модулът JSON-B съхранява шест пакета:

  • javax.json.bind: Определя входната точка за обвързване на Java обекти с JSON документи.
  • javax.json.bind.adapter: Дефинира класове, свързани с адаптера.
  • javax.json.bind.annotation: Дефинира анотации за персонализиране на картографирането между програмните елементи на Java и JSON документите.
  • javax.json.bind.config: Определя стратегии и политики за персонализиране на картографирането между програмните елементи на Java и JSON документите.
  • javax.json.bind.serializer: Определя интерфейси за създаване на персонализирани сериализатори и десериализатори.
  • javax.json.bind.spi: Определя интерфейс на доставчик на услуги (SPI) за включване на персонализирани JsonbBuilders.

Уебсайтът на JSON-B също предоставя връзка към Yasson, Java рамка, която осигурява стандартен обвързващ слой между Java класовете и JSON документите, и официална справочна реализация на JSON Binding API.

JSON-B и Java EE 8

Подобно на JSON-P, JSON-B първоначално беше обмислен за включване в Java SE, но вместо това беше включен в изданието Java EE 8. Все пак можете да работите с JSON-B в контекста на Java SE.

Изтеглете и инсталирайте JSON-B

JSON-B 1.0 е текущата версия към момента на писане. Можете да получите справочната реализация на Yasson на тази библиотека от хранилището на Maven. Ще трябва да изтеглите следните JAR файлове:

  • Javax JSON Bind API 1.0: Съдържа всички JSON-B класни файлове. Изтеглих javax.json.bind-api-1.0.jar.
  • Ясон: Съдържа базирана на Eclipse референтна реализация на JSON-B. Изтеглих yasson-1.0.3.jar.
  • JSR 374 (JSON обработка) Доставчик по подразбиране: Съдържа всички файлове на класа JSON-P 1.0, заедно с файловете по подразбиране на доставчика на Glassfish. Изтеглих javax.json-1.1.4.jar.

Добавете тези JAR файлове към своя път на класа, когато компилирате и изпълнявате код, който използва тези библиотеки:

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

Сериализиране и десериализиране на Java обекти с JSON-B

В javax.json.bindпакета осигурява Jsonbи JsonbBuilderинтерфейсите, които служат като entrypoint за тази библиотека:

  • Jsonbпредоставя претоварени toJson()методи за сериализиране на дървета на Java обекти към JSON документи и fromJson()методи за десериализиране на JSON документи към дървета на Java обекти.
  • JsonbBuilderпредоставя newBuilder()и други методи за получаване на нов конструктор и build()и create()методи за връщане на нови Jsonbобекти.

Следният код пример показва основния ползването на Jsonbи JsonBuilderтипове:

// 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);

Този пример се позовава Jsonbе String toJson(Object object)метод за сериализирате на Java обект, ( Employee). Този метод се предава на корена на Java обектното дърво за сериализиране. Ако nullе приет, toJson()хвърля java.lang.NullPointerException. Изхвърля, javax.json.bind.JsonbExceptionкогато по време на сериализацията възникне неочакван проблем (като грешка при входа / изхода).

Този код фрагмент също се позовава Jsonbе T fromJson(String str, Class type)генеричен метод, който се използва за deserialization. Този метод се предава на базата на низове JSON документ, за да десериализира и типа на получения корен обект на дървото на обект Java, който се връща. Този метод хвърля, NullPointerExceptionкогато nullе предаден на който и да е параметър; изхвърля, JsonbExceptionкогато възникне неочакван проблем по време на десериализацията.

Извадих фрагмента на код от JSONBDemoприложение, което предоставя основна демонстрация на JSON-B. Листинг 1 представя изходния код за тази демонстрация.

Листинг 1. JSONBDemo.java (версия 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()първо създава Jsonbобект, последван от Employeeобект. След това извиква toJson()да сериализира Employeeобекта в JSON документ, който се съхранява в низ. След отпечатване на този документ, main()извиква fromJson()с предишния низ и обект на Employee', за java.lang.Classда десериализира JSON документа към друг Employeeобект, който впоследствие се отпечатва.

Листинг 2 представя Employeeизходния код.

Листинг 2. Employee.java (версия 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(); } }

Съставете списъци 1 и 2, както следва:

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

Стартирайте приложението, както следва:

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

Допълнителни видове, като например java.math.BigInteger, java.util.Dateи java.time.LocalDateсе поддържат. Вижте спецификацията JSON-B за пълен списък на поддържаните типове.

Сериализиране и десериализиране на масиви и колекции с JSON-B

Предишният раздел се фокусира върху сериализиране и десериализиране на отделни Java обекти. JSON-B също поддържа възможността за сериализиране и десериализиране на обектни масиви и колекции. Листинг 3 предоставя демонстрация.

Листинг 3. JSONBDemo.java (версия 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); } }

Листинг 3 е просто разширение на Листинг 1 и използва същия Employeeклас, представен в Листинг 2. Освен това, този пример на код извиква същото toJson()и fromJson()методи.