糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > JAXB 深入显出 - JAXB 教程 XML转Java对象深入(Unmarshaller)

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

时间:2023-07-05 12:43:33

相关推荐

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

摘要:JAXB 作为JDK的一部分,能便捷地将Java对象与XML进行相互转换,本教程从实际案例出发来讲解JAXB 2 的那些事儿。完整版目录

前情回顾

上一节以简单介绍了 UnMarshaller 的过程,主要介绍了多种数据源如何处理。这一节将深入介绍XML数据转换为JAVA对象,将涉及更加复杂的XML结构。

Unmarshaller Callback

在JAXB反序列化时,有两个方法可以自定义一些行为,它们有固定的形式:

void beforeUnmarshal(Unmarshaller unmarshaller, Object parent) {}

void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {}

上一节中的Employe经过改造:

package com.example.demo.lesson17;import java.io.Serializable;import javax.xml.bind.Unmarshaller;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement(name= "Employe")@XmlAccessorType(XmlAccessType.FIELD)public class Employe implements Serializable{private static final long serialVersionUID = 1L;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;}void beforeUnmarshal(Unmarshaller unmarshaller, Object parent) {System.out.println("调用Unmarshaller之前");}void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {System.out.println("调用Unmarshaller之后");}@Overridepublic String toString() {return "Employee [id=" + id + ", name=" + name + "]";}}

测试一下:

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

结果:

调用Unmarshaller之前调用Unmarshaller之后Employee [id=1504, name=Test]

这两个方法在某些场合可以起到自定义 Unmarshaller 的效果。

复杂XML转化

之前见到的XML都是一层结构,真实场景中的XML肯定复杂的多。但是对于特别复杂的XML结构,我不会深入,因为XML都是一级一级的结构,再复杂的XML也是多级拼接而成,于是正确的拆分XML便是反序列化中重要的一环。

<employee id="17"><department><id>101</id><name>IT</name></department><firstName>Lokesh</firstName><lastName>Gupta</lastName></employee>

对于这个XML,需要把XML拆分成两部分:最外层的employe和嵌套的department。如果遇到XML中是属性的,在Java bean的字段上添加注解@XmlAttribute,需要名称不一样的,添加别名@XmlElement(name="FirstName")

Employee的部分重要代码:

@XmlRootElement(name = "employee")@XmlAccessorType(XmlAccessType.FIELD)public class Employee {@XmlAttributeprivate Integer id;@XmlElement(name="FirstName")private String firstName;private String lastName;private Department department;// ignore setters/getters,toString}

Department的完整代码:

package com.example.demo.lesson17;public class Department {public String id;public String name;@Overridepublic String toString() {return "Department [id=" + id + ", name=" + name + "]";}}

因为比较简单,不需要任何注解,看起来好像和JAXB无关的Department。

测试一下:

@Testpublic void test2() throws JAXBException {JAXBContext context = JAXBContext.newInstance(Employee.class);Unmarshaller unmarshaller = context.createUnmarshaller();String xmlStr = "<employee id='17'>\r\n" + " <department>\r\n" + " <id>101</id>\r\n" + " <name>IT</name>\r\n" + " </department>\r\n" + " <FirstName>Lokesh</FirstName>\r\n" + " <id>1</id>\r\n" + " <lastName>Gupta</lastName>\r\n" + "</employee>";Employee employee = (Employee)unmarshaller.unmarshal(new StringReader(xmlStr));System.out.println(employee);//Employee [id=17, firstName=Lokesh, lastName=Gupta, department=Department [id=101, name=IT]]}

得到的结果:

Employee [id=17, firstName=Lokesh, lastName=Gupta, department=Department [id=101, name=IT]]

所有的字段都反序列化成功了,不仅仅得到了Employee,还得到了Department数据。

有的XML显得更为复杂,像下面这种:

<MUSEUMS><MUSEUM children_allowed="false"><MUSEUM_NAME>Reina Sofia Museum</MUSEUM_NAME><CITY>Madrid</CITY><PERMANENT_EXHIBITION><NAME>Permanent Exhibition - Reina Sofia Museum</NAME><ARTIST>Picasso</ARTIST><ARTIST>Dali</ARTIST><ARTIST>Miro</ARTIST><FROM>1900-01-01</FROM><TO>-12-31</TO></PERMANENT_EXHIBITION></MUSEUM><MUSEUM><MUSEUM_NAME>Louvre Museum</MUSEUM_NAME><CITY>Paris</CITY><PERMANENT_EXHIBITION><NAME>Permanent Exhibition - Louvre Museum</NAME><ARTIST>Leonardo da Vinci</ARTIST><ARTIST>Caravaggio</ARTIST><ARTIST>Delacroix</ARTIST></PERMANENT_EXHIBITION></MUSEUM><TOTAL>2</TOTAL></MUSEUMS>

这种XML结构在业务场景更普遍,它们很长,看着很复杂,其实并没有想象的那么难。这个数据看着复杂,其实更多的是重复,既然都是一样的,那就需要巧用‘循环’了。而Java bean中的循环当然要考虑List,它里面包含的数据都是相同类型,结构必然一样,把上面这段XML拆分后,就得到了3个Java bean。

最外层的Java bean:

@XmlRootElement(name = "MUSEUMS")@XmlAccessorType(XmlAccessType.FIELD)public class Museums {@XmlElement(name = "MUSEUM")List<Museum> museums;@XmlElement(name = "TOTAL")String total;// ignore setters/getters,toString}

接下来的Meseum:

@XmlRootElement( name = "MUSEUM" )@XmlType( propOrder = {"name", "city", "special" } )@XmlAccessorType(XmlAccessType.FIELD)public class Museum {@XmlElement(name = "MUSEUM_NAME")String name;@XmlAttribute(name = "children_allowed", required=false)Boolean childrenAllowed;@XmlElement(name = "CITY")String city;@XmlElement(name = "PERMANENT_EXHIBITION")Exhibition special;// ignore setters/getters,toString}

接下来的一层:

@XmlAccessorType(XmlAccessType.FIELD)public class Exhibition {@XmlElement(name = "NAME")String name;@XmlElement(name = "ARTIST")List<String> artist;@XmlElement(name = "FROM")String from;@XmlElement(name = "TO")String to;// ignore setters/getters,toString}

演示代码比较长:

@Testpublic void test3() throws JAXBException {JAXBContext context = JAXBContext.newInstance(Museums.class);Unmarshaller unmarshaller = context.createUnmarshaller();String xmlStr = "<MUSEUMS>\r\n" + " <MUSEUM children_allowed=\"false\">\r\n" + " <MUSEUM_NAME>Reina Sofia Museum</MUSEUM_NAME>\r\n" + " <CITY>Madrid</CITY>\r\n" + " <PERMANENT_EXHIBITION>\r\n" + "<NAME>Permanent Exhibition - Reina Sofia Museum</NAME>\r\n" + "<ARTIST>Picasso</ARTIST>\r\n" + "<ARTIST>Dali</ARTIST>\r\n" + "<ARTIST>Miro</ARTIST>\r\n" + "<FROM>1900-01-01</FROM>\r\n" + "<TO>-12-31</TO>\r\n" + " </PERMANENT_EXHIBITION>\r\n" + " </MUSEUM>\r\n" + " <MUSEUM>\r\n" + " <MUSEUM_NAME>Louvre Museum</MUSEUM_NAME>\r\n" + " <CITY>Paris</CITY>\r\n" + " <PERMANENT_EXHIBITION>\r\n" + "<NAME>Permanent Exhibition - Louvre Museum</NAME>\r\n" + "<ARTIST>Leonardo da Vinci</ARTIST>\r\n" + "<ARTIST>Caravaggio</ARTIST>\r\n" + "<ARTIST>Delacroix</ARTIST>\r\n" + " </PERMANENT_EXHIBITION>\r\n" + " </MUSEUM>\r\n" + " <TOTAL>2</TOTAL>\r\n" + "</MUSEUMS>";Museums museums = (Museums)unmarshaller.unmarshal(new StringReader(xmlStr));System.out.println(museums);//Museums [museums=[Museum [name=Reina Sofia Museum, childrenAllowed=false, city=Madrid, special=Exhibition [name=Permanent Exhibition - Reina Sofia Museum, artist=[Picasso, Dali, Miro], from=1900-01-01, to=-12-31]], Museum [name=Louvre Museum, childrenAllowed=null, city=Paris, special=Exhibition [name=Permanent Exhibition - Louvre Museum, artist=[Leonardo da Vinci, Caravaggio, Delacroix], from=null, to=null]]], total=2]}

XML中所有的元素都被正确识别。

无论多么复杂的XML结构,都离不开这几种拼接形式,嵌套的越多,需要越多的Java对象与之对应。

对于一些需要特殊处理的数据,需要使用到适配器来私人订制。

完整代码

可以在GitHub找到完整代码。

本节代码均在该包下:package com.example.demo.lesson17;

下节预览

本节介绍了 JAXB 将复杂 XML 转化为Java对象。下一节开始,讲述JAXB对于JSON的支持场景。

如果觉得《JAXB 深入显出 - JAXB 教程 XML转Java对象深入(Unmarshaller)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。