文章21 | 阅读 8238 | 点赞0
摘要: JAXB 作为JDK的一部分,能便捷地将Java对象与XML进行相互转换,本教程从实际案例出发来讲解JAXB 2 的那些事儿。完整版目录
上一节以简单介绍了 UnMarshaller 的过程,主要介绍了多种数据源如何处理。这一节将深入介绍XML数据转换为JAVA对象,将涉及更加复杂的XML结构。
在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之后");
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
}
测试一下:
@Test
public 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便是反序列化中重要的一环。
<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 {
@XmlAttribute
private 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;
@Override
public String toString() {
return "Department [id=" + id + ", name=" + name + "]";
}
}
因为比较简单,不需要任何注解,看起来好像和JAXB无关的Department。
测试一下:
@Test
public 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>2014-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
}
演示代码比较长:
@Test
public 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>2014-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=2014-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的支持场景。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://jiangchao.blog.csdn.net/article/details/84668004
内容来源于网络,如有侵权,请联系作者删除!