在現今的項目開發中,雖然數據的傳輸大部分都是用json格式來進行傳輸,但是xml畢竟也會有一些老的項目在進行使用,正常的老式方法是通過獲取節點來進行一系列操作,個人感覺太過於復雜、繁瑣。推薦一套簡單的api--XStream類。在理解了原理的情況下看下注解的語法即會使用
例子是把xml映射成bean對象
這個是要映射的xml代碼
<?xml version="1.0" encoding="UTF-8"?> <c c1="0"> <d d1="101280101" d2="廣州" d3="guangzhou" d4="廣東"/> <d d1="101280102" d2="番禺" d3="panyu" d4="廣東"/> <d d1="101280103" d2="從化" d3="conghua" d4="廣東"/> </c>
xml的代碼結構很簡單,可以看作是城市列表集合
城市的bean
@Data @AllArgsConstructor @NoArgsConstructor public class City { private String cityId; private String cityName; private String cityCode; private String province;
}
這樣就與xml的d
元素中的屬性一一對應了
然后再寫個城市列表的bean
@Data @AllArgsConstructor @NoArgsConstructor public class CityList { private List<City> cityList; }
以上的實體類bean
的set/get
方法都使用lombok
生成了
下面我們把xml代碼轉換成對象
第一種方法是使用 JAXB(Java Architecture for XML Binding) 實現XML與Bean的相互轉換
簡介
JAXB是一個業界的標准,是一項可以根據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屬性。
具體使用
首先要在之前准備好的bean上加上相關注解
城市Bean
//根元素 @XmlRootElement(name = "d") //訪問類型,通過字段 @XmlAccessorType(XmlAccessType.FIELD) @Data @AllArgsConstructor @NoArgsConstructor public class City { @XmlAttribute(name = "d1") private String cityId; @XmlAttribute(name = "d2") private String cityName; @XmlAttribute(name = "d3") private String cityCode; @XmlAttribute(name = "d4") private String province; }
城市集合
@XmlRootElement(name = "c") @XmlAccessorType (XmlAccessType.FIELD) @Data @AllArgsConstructor @NoArgsConstructor public class CityList { @XmlElement(name = "d") private List<City> cityList; }
需要指定bean中的屬性和xml的屬性一一對應
需要有個工具類XmlBuilder
,主要是將XML轉為指定的對象
里面只需要一個方法
public class XmlBuilder { /** * 將XML轉為指定的POJO * @param clazz * @param xmlStr * @return * @throws Exception */ public static Object xmlStrToOject(Class<?> clazz, String xmlStr) throws Exception { Object xmlObject = null; Reader reader = null; JAXBContext context = JAXBContext.newInstance(clazz); // XML 轉為對象的接口 Unmarshaller unmarshaller = context.createUnmarshaller(); reader = new StringReader(xmlStr); //以文件流的方式傳入這個string xmlObject = unmarshaller.unmarshal(reader); if (null != reader) { reader.close(); } return xmlObject; } }
這個方法有兩個參數Class<?> clazz
, String xmlStr
,Class<?> clazz
:指定我們需要轉換的對象,xmlStr
:需要轉的xml字符串
轉換方法已經寫好了,下面就來調用,先讀取xml文件,再調用工具類的方法把XML轉為Java對象
public List<City> listCity() throws Exception { // 讀取XML文件 Resource resource = new ClassPathResource("citylist.xml"); BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream(), "utf-8")); StringBuffer buffer = new StringBuffer(); String line = ""; while ((line = br.readLine()) !=null) { buffer.append(line); } br.close();
// XML轉為Java對象 CityList cityList = (CityList)XmlBuilder.xmlStrToOject(CityList.class, buffer.toString()); return cityList.getCityList(); }
通過spring
提供的ClassPathResource
可以讀取,指定類路徑下的資源文件名稱就可以讀取到
下面需要使用 BufferedReader
把xml
讀取出來,把xml
中所有內容都以讀取出來並寫入到buffer
字符串中.。
后面把需要需要轉的對象和讀取出來的內容字符串傳入轉換方法就可以了
第二種方法是使用XStream
利用XStream在Java對象和XML之間相互轉換
簡介
Xstream是一種OXMapping
技術,是用來處理XML
文件序列化的框架,在將JavaBean
序列化,或將XML
文件反序列化的時候,不需要其它輔助類和映射文件,使得XML
序列化不再繁索。Xstream也可以將JavaBean
序列化成Json
或反序列化,使用非常方便。
主要使用
@XStreamAlias(“alis”)
java對象在xml中以標簽的形式顯示時,如果名字與類名或者屬性名不一致,可以使用該標簽並在括號內注明別名。
@XStreamOmitField
在輸出XML的時候忽略該屬性
@XStreamImplicit
如果該屬性是一個列表或者數組,在XML中不顯示list或者Array字樣
@XStreamAsAttribute
該屬性不單獨顯示成XML節點,而是作為屬性顯示出來
@XStreamContainedType
@XStreamConverter
設置轉換器
@XStreamConverters
converter主要用於將某些字段進行復雜的轉換,轉換過程寫在一個類中。
然后將其注冊到XStream。
springboot使用XStream需要引入依賴
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.10</version> </dependency>
然后在bean中加上相關注解
城市bean
@Data @AllArgsConstructor @NoArgsConstructor @XStreamAlias("d") public class City { @XStreamAsAttribute @XStreamAlias("d1") private String cityId; @XStreamAsAttribute @XStreamAlias("d2") private String cityName; @XStreamAlias("d3") @XStreamAsAttribute private String cityCode; @XStreamAsAttribute @XStreamAlias("d4") private String province; }
城市集合bean
@Data @AllArgsConstructor @NoArgsConstructor @XStreamAlias("c") public class CityList { @XStreamImplicit(itemFieldName="d") private List<City> cityList; }
重命名注解:@XStreamAlias()
省略集合根節點:@XStreamImplicit
把字段節點設置成屬性:@XStreamAsAttribute
這些命名都需要和解析的xml的屬性名一一對應,一旦不對應就會報com.thoughtworks.xstream.mapper.CannotResolveClassException
異常,找不到對應的類屬性
集合屬性的需要使用:@XStreamImplicit
,不然會報com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$DuplicateFieldException
轉換器映射異常
同樣也需要寫個轉換的工具類
public class XsteamUtil { public static Object toBean(Class<?> clazz, String xml) { Object xmlObject = null; XStream xstream = new XStream(); xstream.processAnnotations(clazz); xstream.autodetectAnnotations(true); xmlObject= xstream.fromXML(xml); return xmlObject; } }
傳參也是一樣,Class<?> clazz
:指定我們需要轉換的對象,xml
:需要轉的xml字符串
這樣工具類就寫好了
拓展了解
XStream提供了很多方法供我們使用
autodetectAnnotations()
自動檢測注解
processAnnotations()
應用傳過來的類的注解
fromXML()
XML反序列化(JSON也是一樣)
toXML()
XML序列化(JSON也是一樣)
自定義解析器
Xstream序列化XML
,解析器用StaxDriver
指定解析器:XStream xstream = new XStream(new StaxDriver());
Xstream序列化Json
,解析器用JettisonMappedXmlDriver
指定解析器:XStream xstream = new XStream(new JettisonMappedXmlDriver());
也可以不具體指定解析器,也是沒問題的
深入了解
XStreamxstream = new XStream();
默認情況下,XStream
會 采用Xpp3
庫,XPP3
是一種運行效率非常高的XML全解析實現。如果你不想依靠Xpp3
庫的話,也可以使用一個標准的JAXP DOM
解析器,可以采用以下語句進行初始化:
//不使用XPP3
庫
XStreamxstream = new XStream(new DomDriver());
此xstream實例,為線程安全的,可以供多個線程進行調用,共享使用。系統提供了多種標識解析器供我們選擇,包括,DomDriver
、 JDomDriver
、StaxDriver
等等。
Xstream提供了對Json的支持,是因為Xstream內置了兩個Driver:
1.JsonHierarchicalStreamDriver
:不依賴其他類庫,只實現 obj->JSON
2.JettisonMappedXmlDriver
:依賴jettison
類庫,實現 JSON->obj
or obj->JSON
兩種Driver在處理相同設置的Object時會得到不同的JSON串,JsonHierarchicalStreamDriver
得到的串更簡潔,確如官網所說。
JsonHierarchicalStreamDriver
有個小問題——默認輸出帶格式的JSON
串,結構中帶空格、換行,並且沒有提供修飾方式。
總的來說,Xstream使用起來更簡便,代碼跟簡單,也容易理解,對於xml和Json都提供了支持,不需要其它輔助類和映射文件,使得XML,Json序列化不再繁瑣,我推薦使用
作者:意識流丶
鏈接:https://www.jianshu.com/p/9e31eeccc485
來源:簡書