JAXB 实现java对象与xml之间互相转换
一、简介
JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到 XML实例文档。
Jaxb 2.0是JDK 1.6的组成部分。我们不需要下载第三方jar包 即可做到轻松转换。Jaxb2使用了JDK的新特性,如:Annotation、GenericType等,需要在即将转换的JavaBean中添加annotation注解。
二、重要概念
- JAXBContext类,是应用的入口,用于管理XML/Java绑定信息。
- Marshaller接口,将Java对象序列化为XML数据。
- Unmarshaller接口,将XML数据反序列化为Java对象。
首先熟悉一下JAXB实现对象与xml互转时常用的一些注解使用:
1.@XmlRootElement,用于类级别的注解,对应xml的跟元素。通过name属性定义这个根节点的名称。
2.@XmlAccessorType,定义映射这个类中的何种类型都需要映射到xml。(如果不存在@XmlAccessorType,默认使用XmlAccessType.PUBLIC_MEMBER注解)
参数:XmlAccessType.FIELD: java对象中的所有成员变量。
XmlAccessType.PROPERTY:java对象中所有通过getter/setter方式访问的成员变量。
XmlAccessType.PUBLIC_MEMBER:java对象中所有的public访问权限的成员变量和通过getter/setter方式访问的成员变量。
XmlAccessType.NONE: java对象的所有属性都不映射为xml的元素。
3.@XmlAttribute,用于把java对象的属性映射为xml的属性,并可通过name属性为生成的xml属性指定别名。
4.@XmlElement,指定一个字段或get/set方法映射到xml的节点。通过name属性定义这个根节点的名称。
5.@XmlElementWrapper,为数组或集合定义一个父节点。通过name属性定义这个父节点的名称。
下面来看一个例子:
先定义一个学生类,Student如下:
package xmldemo;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
/**
* @author aionbo
* @type_name Student
* @description TODO
* @date 2017年3月7日 上午11:36:25
*/
public class Student {
String name; // 姓名
String sex; // 性别
int number; // 学号
String className; // 班级
List<String> hobby; // 爱好
public Student() {
}
public Student(String name, String sex, int number, String className,
List<String> hobby) {
this.name = name;
this.sex = sex;
this.number = number;
this.className = className;
this.hobby = hobby;
}
@XmlAttribute(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlAttribute(name = "sex")
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@XmlAttribute(name = "number")
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@XmlElement(name = "className")
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
@XmlElementWrapper(name = "hobbys")
@XmlElement(name = "hobby")
public List<String> getHobby() {
return hobby;
}
public void setHobby(List<String> hobby) {
this.hobby = hobby;
}
}
切记,如果java对象属性同时添加了get和set方法,注解不能定义在属性的定义上,只需在get或者set方法上定义一个即可,否则jaxb会报错!!如下:
Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "name"
然后再定义学生集合类,StudentList如下:
package xmldemo;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author aionbo
* @type_name StudentList
* @description TODO
* @date 2017年3月7日 上午11:40:18
*/
@XmlRootElement(name = "list")
public class StudentList {
List<Student> students; // 所有学生信息的集合
@XmlElement(name = "student")
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
最后写xml和java对象互转的类(通过Marshaller类实现将对象转换为xml,同时也可利用Unmarshaller类进行xml转换为类):
1.java对象转换为xml:
package xmldemo;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
/**
* @author aionbo
* @type_name BeanToXML
* @description TODO
* @date 2017年3月7日 上午11:43:36
*/
public class BeanToXML {
/**
* java对象转换为xml文件
* @param xmlPath xml文件路径
* @param load java对象.Class
* @return xml文件的String
* @throws JAXBException
*/
public static String beanToXml(Object obj,Class<?> load) throws JAXBException{
JAXBContext context = JAXBContext.newInstance(load);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
StringWriter writer = new StringWriter();
marshaller.marshal(obj,writer);
return writer.toString();
}
public static void main(String[] args) throws JAXBException, IOException {
List<String> hobby = new ArrayList<>();
hobby.add("篮球");
hobby.add("音乐");
hobby.add("乒乓球");
List<Student> studentList = new ArrayList<>();
Student st = new Student("张三","男",10001,"尖子班",hobby);
studentList.add(st);
Student st1 = new Student("李四","男",10002,"普通班",hobby);
studentList.add(st1);
Student st2 = new Student("莉莉","女",10003,"普通班",hobby);
studentList.add(st2);
StudentList students = new StudentList();
students.setStudents(studentList);
//转换
String str = BeanToXML.beanToXml(students, StudentList.class);
//写入到xml文件中
File file=new File("C:\\Users\\Administrator\\Desktop\\test.xml");
if(!file.exists()){
file.createNewFile();
}
BufferedWriter bfw = new BufferedWriter(new FileWriter(file));
bfw.write(str);
bfw.close();
}
}
测试生成的xml文件如下图:
2.xml转换为java对象:
package xmldemo;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
/**
* @author aionbo
* @type_name XMLToBean
* @description TODO
* @date 2017年3月7日 上午11:54:07
*/
public class XMLToBean {
/**
* xml文件配置转换为对象
* @param xmlPath xml文件路径
* @param load java对象.Class
* @return java对象
* @throws JAXBException
* @throws IOException
*/
public static Object xmlToBean(String xmlPath,Class<?> load) throws JAXBException, IOException{
JAXBContext context = JAXBContext.newInstance(load);
Unmarshaller unmarshaller = context.createUnmarshaller();
File file=new File(xmlPath);
if(!file.exists()){
file.createNewFile();
}
Object object = unmarshaller.unmarshal(file);
return object;
}
public static void main(String[] args) throws IOException, JAXBException {
String xmlPath = "C:\\Users\\Administrator\\Desktop\\test.xml";
Object object = XMLToBean.xmlToBean(xmlPath,StudentList.class);
StudentList students = (StudentList)object;
List<Student> studentList = students.getStudents();
for(int i=0;i<studentList.size();i++){
System.out.println(studentList.get(i).name);
System.out.println(studentList.get(i).sex);
System.out.println(studentList.get(i).number);
System.out.println(studentList.get(i).className);
for(String str :studentList.get(i).hobby){
System.out.print(str+" ");
}
System.out.println();
System.out.println("-------------");
}
}
}
测试打印的结果如下:
张三
男
10001
尖子班
篮球 音乐 乒乓球
-------------
李四
男
10002
普通班
篮球 音乐 乒乓球
-------------
莉莉
女
10003
普通班
篮球 音乐 乒乓球
-------------
有不明白的可以联系我,互相交流!
jaxb虽然挺实用,但是在xml转java对象时xml文件不能配置错了,必须严格按照自己定义的java对象的注解来编写xml文件,否则jaxb里面报错很难查错!!!