JAXB 深入显出 - JAXB 教程 XML转Java对象初探(Unmarshaller)

x33g5p2x  于2021-12-28 转载在 其他  
字(5.1k)|赞(0)|评价(0)|浏览(337)

摘要: 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对象的高级操作。

相关文章