1. 程式人生 > >JAXB 深入顯出 - JAXB 教程 XML轉Java物件初探(Unmarshaller)

JAXB 深入顯出 - JAXB 教程 XML轉Java物件初探(Unmarshaller)

摘要: JAXB 作為JDK的一部分,能便捷地將Java物件與XML進行相互轉換,本教程從實際案例出發來講解JAXB 2 的那些事兒。完整版目錄

前情回顧

之前介紹的都是將Java物件轉換為XML,這一節開始,將講述XML資料轉換為JAVA物件。

資料準備

現在有一段XML資料如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Employee>
    <id>111</id>
    <name>Test</name>
</
Employee
>

我將其保存於檔案lesson16.xml中。

下面是一個經典的Java bean宣告方式,加入了JAXB標籤,並且實現了toString()方法便於除錯。

@XmlRootElement(name= "Employee")
public class Employee {
	private String id;
	private String name;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName
() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Employee [id=" + id + ", name=" + name + "]"; } }

XML檔案

下面演示了將XML檔案資料反編組(反序列化):

	@Test
	public void test1() throws JAXBException {
		JAXBContext context = JAXBContext.
newInstance(Employee.class); Unmarshaller unmarshaller = context.createUnmarshaller(); Employee employee = (Employee)unmarshaller.unmarshal(new File("./src/test/resources/lesson16.xml")); System.out.println(employee);//Employee [id=111, name=Test] }

得到的結果:
Employee [id=111, name=Test]

XML stream

下面演示了將XML stream資料反編組(反序列化):

	@Test
	public void test11() throws JAXBException {
		JAXBContext context = JAXBContext.newInstance(Employee.class);
		Unmarshaller unmarshaller = context.createUnmarshaller();
		Employee employee = (Employee)unmarshaller.unmarshal(GenerateBean.class.getResourceAsStream("/lesson16.xml"));
		System.out.println(employee);//Employee [id=111, name=Test]
	}

得到的結果:
Employee [id=111, name=Test]

XML InputStream

下面演示了將XML InputStream 資料反編組(反序列化):

	@Test
	public void test2() throws JAXBException, IOException {
		JAXBContext context = JAXBContext.newInstance(Employee.class);
		Unmarshaller unmarshaller = context.createUnmarshaller();
		InputStream is = new FileInputStream("./src/test/resources/lesson16.xml");
		Employee employee = (Employee)unmarshaller.unmarshal(is);
		System.out.println(employee);//Employee [id=111, name=Test]
	}

得到的結果:
Employee [id=111, name=Test]

XML URL

在演示URL前,先說明一下資料。我在w3school 上找到一個XML文件,其地址http://www.w3school.com.cn/example/xmle/note.xml,內容如下:

<note>
    <to>George</to>
    <from>John</from>
    <heading>Reminder</heading>
    <body>Don't forget the meeting!</body>
</note>

為此,我準備了Java bean如下:

@XmlRootElement
public class Note {

	private String to;
	private String from;
	private String heading;
	private String body;
//  ignore setters/getters,toString
}

下面演示了將XML URL 資料反編組(反序列化):

	@Test
	public void test3() throws JAXBException, IOException {
		JAXBContext context = JAXBContext.newInstance(Note.class);
		Unmarshaller unmarshaller = context.createUnmarshaller();
		URL url = new URL("http://www.w3school.com.cn/example/xmle/note.xml");
		Note note = (Note)unmarshaller.unmarshal(url);
		System.out.println(note);//Note [to=George, from=John, heading=Reminder, body=Don't forget the meeting!]
	}

得到的結果:
Note [to=George, from=John, heading=Reminder, body=Don't forget the meeting!]

XML StreamSource

下面演示了將XML StreamSource 資料反編組(反序列化):

	@Test
	public void test4() throws JAXBException, IOException {
		JAXBContext context = JAXBContext.newInstance(Employee.class);
		Unmarshaller unmarshaller = context.createUnmarshaller();
		String xmlStr = "<Employee><id>1504</id><name>Test</name></Employee>";
		Employee employee = (Employee)unmarshaller.unmarshal(new StreamSource(new StringReader(xmlStr)));
		System.out.println(employee);//Employee [id=1504, name=Test]
	}

得到的結果:
Employee [id=1504, name=Test]

XML Node

下面演示了將XML Document 資料反編組(反序列化):

@Test
	public void test5() throws Exception {
		JAXBContext context = JAXBContext.newInstance(Employee.class);
		Unmarshaller unmarshaller = context.createUnmarshaller();
		//建立 Document
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document document = db.parse(new File("./src/test/resources/lesson16.xml"));
		Employee employee = (Employee)unmarshaller.unmarshal(document);
		System.out.println(employee);//Employee [id=111, name=Test]
	}

得到的結果:
Employee [id=111, name=Test]

方法延伸

一般來說,unmarshaller.unmarshal()返回一個Object,需要強制型別轉換,才能得到想要的結果。而有幾個資料來源不止能返回Object,還可以返回JAXBElement,像下面這樣:

    @Test
	public void test6() throws Exception {
		JAXBContext context = JAXBContext.newInstance(Employee.class);
		Unmarshaller unmarshaller = context.createUnmarshaller();
		//建立 Document
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document document = db.parse(new File("./src/test/resources/lesson16.xml"));
		JAXBElement<Employee> ele = unmarshaller.unmarshal(document, Employee.class);
		System.out.println(ele.getValue());//Employee [id=111, name=Test]
	}

過載方法unmarshaller.unmarshal() 接收兩個引數,第二個引數就是我們需要的型別,然後使用其 getValue() 獲取資料,避免強制型別轉換。

靜態方法

在之前已經接觸過JAXB的靜態方法,它可以簡化程式碼,並且易用性也大大提高。

	@Test
	public void test7() throws JAXBException {
		Employee employee = JAXB.unmarshal(new File("./src/test/resources/lesson16.xml"), Employee.class);
		System.out.println(employee);//Employee [id=111, name=Test]
	}

得到相同的結果:
Employee [id=111, name=Test]

還有很多種方式沒有列舉,它們的應用場景不多,反序列化和序列化也大同小異,因此沒有全部演示。

Unmarshalling 可以反序列化整個XML或者XML文件的一部分。

Unmarshalling 不會返回 null,如果無法將XML對映到Java物件,程式將直接報錯。

完整程式碼

可以在GitHub找到完整程式碼。
本節程式碼均在該包下:package com.example.demo.lesson16;

下節預覽

本節介紹了 JAXB 將 XML 轉化為Java物件的高階操作。