Java XML และ JSON: การประมวลผลเอกสารสำหรับ Java SE ตอนที่ 2: JSON-B

ในบทความนี้เราจะสำรวจ XML และ JSON ใน Java 11 และอื่น ๆ ต่อไป

ตัวอย่างในบทความนี้จะแนะนำให้คุณรู้จัก JSON-B, JSON Binding API สำหรับ Java หลังจากดูภาพรวมและคำแนะนำในการติดตั้งอย่างรวดเร็วฉันจะแสดงวิธีใช้ JSON-B เพื่อทำให้เป็นอนุกรมและแยกสถานะออบเจ็กต์อาร์เรย์และคอลเล็กชัน Java วิธีปรับแต่ง serialization และ deserialization โดยใช้ JSON-B; และวิธีใช้อะแด็ปเตอร์ JSON-B เพื่อแปลงอ็อบเจ็กต์ต้นทางเป็นอ็อบเจ็กต์เป้าหมายในระหว่างการทำให้เป็นอนุกรมหรือการดีซีเรียลไลเซชัน

วัสดุสำหรับบทความนี้เป็นของใหม่อย่างสมบูรณ์ แต่อาจจะพิจารณาบทเพิ่มเติม (บทที่ 13) สำหรับหนังสือเล่มใหม่ของฉันตีพิมพ์เมื่อเร็ว ๆ นี้โดย Apress: Java XML และ JSON พิมพ์ครั้งที่สอง

เกี่ยวกับหนังสือ: Java XML และ JSON

ขณะที่ผมใช้ร่วมกันในบทความก่อนหน้านี้ของฉัน Apress มีการเผยแพร่เพียงรุ่นที่สองของหนังสือของฉันJava XML และ JSON เป็นเรื่องน่ายินดีที่ได้เขียนหนังสือทั้งเล่มเกี่ยวกับ XML และ JSON ซึ่งเป็นเทคโนโลยีสองอย่างที่ฉันคิดว่าเสริมกันมากกว่าการแข่งขัน หลังจากตีพิมพ์หนังสือฉันได้เพิ่มตัวอย่างใหม่สำหรับบทที่ 6: การแปลงเอกสาร XML ด้วย XSLT และสำหรับบทที่ 11: การประมวลผล JSON ด้วย Jackson บทความล่าสุดของฉัน "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

JSON-B API

เว็บไซต์ Java API สำหรับ JSON Binding (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: กำหนดอินเทอร์เฟซสำหรับการสร้าง serializers และ deserializers ที่กำหนดเอง
  • javax.json.bind.spi: กำหนด Service Provider Interface (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.
  • Yasson: มีการใช้งานอ้างอิงตาม Eclipse ของ JSON-B ฉันดาวน์โหลดyasson-1.0.3.jar.
  • JSR 374 (การประมวลผล JSON) ผู้ให้บริการดีฟอลต์: มีไฟล์คลาส JSON-P 1.0 ทั้งหมดพร้อมกับคลาสไฟล์ผู้ให้บริการเริ่มต้นของ Glassfish ฉันดาวน์โหลดjavax.json-1.1.4.jar.

เพิ่มไฟล์ JAR เหล่านี้ใน classpath ของคุณเมื่อคอมไพล์และรันโค้ดที่ใช้ไลบรารีเหล่านี้:

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อินเตอร์เฟซซึ่งทำหน้าที่เป็นจุดเข้าใช้งานในห้องสมุดนี้:

  • JsonbจัดเตรียมtoJson()เมธอดที่โอเวอร์โหลดสำหรับการจัดลำดับทรีของอ็อบเจ็กต์ Java ไปยังเอกสาร JSON และfromJson()วิธีการ deserializing เอกสาร 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's String toJson(Object object)วิธีการทำให้เป็นอันดับวัตถุ Java ( Employee) วิธีนี้ถูกส่งผ่านรูทของโครงสร้างวัตถุ Java เพื่อทำให้เป็นอนุกรม ถ้าnullจะผ่านพ่นtoJson() java.lang.NullPointerExceptionจะพ่นjavax.json.bind.JsonbExceptionเมื่อเกิดปัญหาที่ไม่คาดคิด (เช่นข้อผิดพลาด I / O) ระหว่างการทำให้เป็นอนุกรม

ส่วนรหัสนี้จะเรียกJsonb's T fromJson(String str, Class type)วิธีการทั่วไปที่ใช้สำหรับการ deserialization เมธอดนี้ถูกส่งผ่านเอกสาร JSON แบบใช้สตริงเพื่อ deserialize และชนิดของรูทของอ็อบเจ็กต์ Java ที่เป็นผลลัพธ์ซึ่งจะส่งคืน วิธีนี้พ่นNullPointerExceptionเมื่อnullถูกส่งไปยังพารามิเตอร์ใดพารามิเตอร์หนึ่ง จะพ่นJsonbExceptionเมื่อมีปัญหาที่ไม่คาดคิดเกิดขึ้นระหว่าง deserialization

ฉันคัดลอกส่วนของโค้ดออกจาก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's java.lang.Classวัตถุ deserialize 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

คุณควรสังเกตผลลัพธ์ต่อไปนี้ (กระจายไปหลายบรรทัดเพื่อให้อ่านง่าย):

{"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] 

กฎสำหรับการทำงานกับ JSON-B

ในขณะที่เล่นกับโปรแกรมนี้ผมสังเกตพฤติกรรมน่าสนใจบางอย่างที่ทำให้ฉันจะกำหนดกฎต่อไปนี้เกี่ยวกับEmployee:

  • ชั้นเรียนจะต้องpublic; มิฉะนั้นข้อยกเว้นจะถูกโยนทิ้ง
  • toJson()จะไม่จัดลำดับฟิลด์ด้วยpublicวิธีการที่ไม่ได้รับ
  • fromJson()จะไม่ยกเลิกการกำหนดค่าฟิลด์ด้วยpublicวิธีการที่ไม่ใช่ตัวกำหนดค่า
  • fromJson()พ่นJsonbExceptionในกรณีที่ไม่มีตัวpublic noargumentสร้าง

ในการแปลงระหว่างช่องออบเจ็กต์ Java และข้อมูล JSON ได้อย่างราบรื่น JSON-B ต้องรองรับ Java ประเภทต่างๆ ตัวอย่างเช่น JSON-B รองรับ Java พื้นฐานต่อไปนี้:

  • 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); } }

Listing 3 เป็นส่วนขยายที่เรียบง่ายของ Listing 1 และใช้Employeeคลาสเดียวกับที่แสดงใน Listing 2 นอกจากนี้ตัวอย่างโค้ดนี้เรียกใช้toJson()และfromJson()วิธีการเดียวกัน