JAXB实现JavaBean与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对象。
- @XmlType,将Java类或枚举类型映射到XML模式类型
- @XmlAccessorType(XmlAccessType.FIELD) ,控制字段或属性的序列化。FIELD表示JAXB将自动绑定Java类中的每个非静态的(static)、非瞬态的(由@XmlTransient标 注)字段到XML。其他值还有XmlAccessType.PROPERTY和XmlAccessType.NONE。
- @XmlAccessorOrder,控制JAXB 绑定类中属性和字段的排序。
- @XmlJavaTypeAdapter,使用定制的适配器(即扩展抽象类XmlAdapter并覆盖marshal()和unmarshal()方法),以序列化Java类为XML。
- @XmlElementWrapper ,对于数组或集合(即包含多个元素的成员变量),生成一个包装该数组或集合的XML元素(称为包装器)。
- @XmlRootElement,将Java类或枚举类型映射到XML元素。
- @XmlElement,将Java类的一个属性映射到与属性同名的一个XML元素。
- @XmlAttribute,将Java类的一个属性映射到与属性同名的一个XML属性。
由@XmlTransient标 注的字段将不会被读取进xml之中,xml转obj的时候也不会赋值!!!
常见错误
单层结构 即类的属性不包含其他类
意外的元素 (uri:"", local:"Merchant")。所需元素为(none)
实体bean那里少了 @XmlRootElement(name="XXX") 了.加上这个注解就可以了
xml实体类 互转实体类定义
实体类 (多层结构 的外层)
@XmlRootElement(name = "Merchants")
@XmlAccessorType(XmlAccessType.FIELD)
public class MerchantList {
@XmlElement(name = "Merchant")
private List<Merchant> MerchantList;
实体类 (多层结构 的内层)
@XmlRootElement(name = "Merchant") --(作为内层时可要可不要,单层结构必须要!)
@XmlAccessorType(XmlAccessType.FIELD)
public class Merchant {
@XmlElement(name = "name")
private String name;
@XmlElement(name = "telenum")
private String telenum;
@XmlElementWrapper(name = "paytypes")
@XmlElement(name = "paytype")
private List<String> paytypes;
xml实体类互转 实现类
/**
* 读取 xml 并转换成 实体类
* @param clazz
* @param filepath
* @return
* @throws FileNotFoundException
*/
@SuppressWarnings("unchecked")
public static <T> T readString(Class<T> clazz, String filepath)
throws FileNotFoundException {
JAXBContext jc;
try {
jc = JAXBContext.newInstance(clazz);
Unmarshaller um = jc.createUnmarshaller();
return (T) um.unmarshal(new FileReader(filepath));
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* 解析bean 将xml转存到指定路径
*
* @param obj
* @param path
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static void beanToXmlFile(Object obj, String path) throws IOException {
JAXBContext jc;
try {
jc = JAXBContext.newInstance(obj.getClass());
Marshaller mu = jc.createMarshaller();
File file = new File(path);
if (!file.exists()) {
file.createNewFile();
}
//JAXB_FORMATTED_OUTPUT 表示输出时 是否将xml格式化
mu.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//JAXB_ENCODING 表示输出时 xml的字符集
//mu.setProperty(Marshaller.JAXB_ENCODING, encoding);
mu.marshal(obj, file);
} catch (JAXBException e) {
e.printStackTrace();
}
}
/**
* 解析bean 将xml 直接输出
*
* @param obj
* @param path
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static String beanToXmlStr(Object obj) throws IOException {
JAXBContext jc;
String result=null;
try {
jc = JAXBContext.newInstance(obj.getClass());
Marshaller mu = jc.createMarshaller();
StringWriter writer=new StringWriter();
mu.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
mu.marshal(obj, writer);
result=writer.toString();
} catch (JAXBException e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) throws IOException {
MerchantList mer = XmlToEntity.readString(MerchantList.class,
"src/Merchant.xml");
System.out.println(mer.toString());
System.out.println();
System.out.println(XmlToEntity.beanToXmlStr(mer));
XmlToEntity.beanToXmlFile(mer, "d:\\tmp\\wtf.xml");
}
待转换的XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<Merchants>
<Merchant>
<name>好奇而已</name>
<telenum>13144445555</telenum>
<paytypes>
<paytype>alipay</paytype>
<paytype>wechat</paytype>
<paytype>baidu</paytype>
</paytypes>
</Merchant>
<Merchant>
<name>烤冷面</name>
<telenum>13233335555</telenum>
<paytypes>
<paytype>alipay</paytype>
<paytype>wechat</paytype>
<paytype>baidu</paytype>
</paytypes>
</Merchant>
</Merchants>
测试结果:
MerchantList [MerchantList=[Merchant [name=好奇而已, telenum=13144445555, paytypes=[alipay, wechat, baidu]],
Merchant [name=烤冷面, telenum=13233335555, paytypes=[alipay, wechat, baidu]]]]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Merchants>
<Merchant>
<name>好奇而已</name>
<telenum>13144445555</telenum>
<paytypes>
<paytype>alipay</paytype>
<paytype>wechat</paytype>
<paytype>baidu</paytype>
</paytypes>
</Merchant>
<Merchant>
<name>烤冷面</name>
<telenum>13233335555</telenum>
<paytypes>
<paytype>alipay</paytype>
<paytype>wechat</paytype>
<paytype>baidu</paytype>
</paytypes>
</Merchant>
</Merchants>