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>