XStream
一、概述
XStream是Java類庫,用來將對象序列化成XML (JSON)或反序列化爲對象。
也就是說,使用XStream,我們可以把Java對象轉換成XML,也可以將XML轉換爲Java對象。
二、XStream相關jar包
XStream的必導JAR包:
- 核心JAR包:
xstream-1.4.7.jar
; - 必須依賴包:
xpp3_min-1.1.4c.jar
(XML Pull Parser,一款速度很快的XML解析器)。
三、創建兩個類
爲了演示我們的XStream的用法,我們先創建兩個類,等會作爲演示操作的對象。
其中一個是City類
:
package com.veeja.demo;
public class City {
private String name;// 市名
private String description;// 描述
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String toString() {
return "City [name=" + name + ", description=" + description + "]";
}
public City() {
super();
// TODO Auto-generated constructor stub
}
public City(String name, String description) {
super();
this.name = name;
this.description = description;
}
}
另一個是Province類
:
package com.veeja.demo;
import java.util.ArrayList;
import java.util.List;
public class Province {
private String name;// 省名
private List<City> cities = new ArrayList<City>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<City> getCities() {
return cities;
}
public void setCities(List<City> cities) {
this.cities = cities;
}
public void addCity(City city) {
cities.add(city);
}
}
四、簡單的示例
使用XStream,步驟也很簡單。
第一步就是創建XStream對象。
XStream xStream = new XStream();
然後就是使用toXML方法來轉換成xml格式的字符串。
String string = xStream.toXML(proList);
例如以下代碼,
我們運行一下下面的function1()
方法,看一下輸出的結果:
@Test
public void function1() {
List<Province> proList = getProvinceList();
/*
* 創建XStream對象,調用toXML把集合轉換成xml字符串
*/
XStream xStream = new XStream();
String string = xStream.toXML(proList);
System.out.println(string);
}
public List<Province> getProvinceList() {
Province p1 = new Province();
p1.setName("北京");
p1.addCity(new City("東城區", "dongchengqu"));
p1.addCity(new City("昌平區", "changpingqu"));
Province p2 = new Province();
p1.setName("山東省");
p1.addCity(new City("濟南", "jinan"));
p1.addCity(new City("青島", "qingdao"));
ArrayList<Province> provinceList = new ArrayList<Province>();
provinceList.add(p1);
provinceList.add(p2);
return provinceList;
}
結果:
<list>
<com.veeja.demo.Province>
<name>北京</name>
<cities>
<com.veeja.demo.City>
<name>東城區</name>
<description>dongchengqu</description>
</com.veeja.demo.City>
<com.veeja.demo.City>
<name>昌平區</name>
<description>changpingqu</description>
</com.veeja.demo.City>
</cities>
</com.veeja.demo.Province>
<com.veeja.demo.Province>
<name>山東省</name>
<cities>
<com.veeja.demo.City>
<name>濟南</name>
<description>jinan</description>
</com.veeja.demo.City>
<com.veeja.demo.City>
<name>青島</name>
<description>qingdao</description>
</com.veeja.demo.City>
</cities>
</com.veeja.demo.Province>
</list>
我們可以觀察一下這個結果:
- 我們可以明顯的看出來,這是一個XML格式的文本。
- 根元素是
<list>
, 因爲我們是把List對象轉換爲xml,所以根元素爲<list>
。 - 第二級爲
<com.veeja.demo.Province>
,因爲我們Javabean的類型爲Province,所以元素的名稱就是類的完整名 - 第三級爲
<name>
和<cities>
,就是Province類內的屬性名。 - 。。。
- 。。。
五、別名
我們在上面生成的xml中,發現了幾個問題:
- 根元素是
<list>
,根據我們的需求,其實這個根元素如果是<china>
更合適一點。 - 還有中間的
<com.veeja.demo.Province>
,都太長了,而且還有類的包名,這裏可以簡要一些,換成小寫,也就是<province>
就可以了。
這個問題怎麼解決呢?答案是使用“別名(alias)”。
我們有這麼幾個需求:
默認List類型對應<list>
元素,希望讓List類型對應<china>
元素;
默認Province類型對應<cn.itcast.demo1.Province>
,希望讓它對應<province>
;
默認City類型對應<cn.itcast.demo1.city>
,希望它對應<city>
元素。
我們可以使用xstream.alias("aaa",Bbb.class);
用來將Bbb類
指定別名爲aaa
。
例如,我們改寫上面的代碼爲:
@Test
public void function2() {
List<Province> proList = getProvinceList();
/*
* 創建XStream對象,調用toXML把集合轉換成xml字符串
*/
XStream xStream = new XStream();
xStream.alias("china", List.class);
xStream.alias("province", Province.class);
xStream.alias("city", City.class);
String string = xStream.toXML(proList);
System.out.println(string);
}
我們再看一下結果,已經變成我們想要的樣子了:
<china>
<province>
<name>北京</name>
<cities>
<city>
<name>東城區</name>
<description>dongchengqu</description>
</city>
<city>
<name>昌平區</name>
<description>changpingqu</description>
</city>
</cities>
</province>
<province>
<name>山東省</name>
<cities>
<city>
<name>濟南</name>
<description>jinan</description>
</city>
<city>
<name>青島</name>
<description>qingdao</description>
</city>
</cities>
</province>
</china>
六、指定屬性、去除無用Collection類的屬性
我們現在不妨把山東省的那一部分單獨拿出來看一看:
<province>
<name>山東省</name>
<cities>
<city>
<name>濟南</name>
<description>jinan</description>
</city>
<city>
<name>青島</name>
<description>qingdao</description>
</city>
</cities>
</province>
首先,我覺得中間的一個cities標籤沒有什麼必要,完全可以去掉,而且name標籤,完全可以作爲province的一個name屬性,而沒有必要單獨生成一個子元素。
也就是經過處理,如果可以得到這樣的形式:
<province name="山東省">
<city>
<name>濟南</name>
<description>jinan</description>
</city>
<city>
<name>青島</name>
<description>qingdao</description>
</city>
</province>
這樣就會簡潔的多。
也就是說,默認情況下,Javabean的屬性都會生成子元素,但是我們希望生成爲元素的屬性。
這時我們可以使用xstream.useAttributeFor(Ccc.class, "name");
來將Ccc類的name屬性,生成<ccc>
的屬性。
我們還可以使用xStream.addImplicitCollection(Province.class, "cities");
來去除Province類的cities(Collection類型的)屬性。
也就是我們再次改寫上面的代碼:
@Test
public void function2() {
List<Province> proList = getProvinceList();
/*
* 創建XStream對象,調用toXML把集合轉換成xml字符串
*/
XStream xStream = new XStream();
xStream.alias("china", List.class);
xStream.alias("province", Province.class);
xStream.alias("city", City.class);
xStream.useAttributeFor(Province.class, "name");
xStream.addImplicitCollection(Province.class, "cities");
String string = xStream.toXML(proList);
System.out.println(string);
}
我們看一下輸出的結果:
<china>
<province name="北京">
<city>
<name>東城區</name>
<description>dongchengqu</description>
</city>
<city>
<name>昌平區</name>
<description>changpingqu</description>
</city>
</province>
<province name="山東省">
<city>
<name>濟南</name>
<description>jinan</description>
</city>
<city>
<name>青島</name>
<description>qingdao</description>
</city>
</province>
</china>
七、去除不想要的Javabean屬性
我們又發現了一個問題,這個<description>
屬性好像沒什麼用處。這個屬性能不能去掉呢?
這個時候,我們可以使用xStream.omitField(City.class, "description");
來去除。
改寫代碼:
@Test
public void function2() {
List<Province> proList = getProvinceList();
/*
* 創建XStream對象,調用toXML把集合轉換成xml字符串
*/
XStream xStream = new XStream();
xStream.alias("china", List.class);
xStream.alias("province", Province.class);
xStream.alias("city", City.class);
xStream.useAttributeFor(Province.class, "name");
xStream.addImplicitCollection(Province.class, "cities");
// 讓city類,名爲description的屬性不生成對應的xml屬性
xStream.omitField(City.class, "description");
String string = xStream.toXML(proList);
System.out.println(string);
}
輸出結果:
<china>
<province name="北京">
<city>
<name>東城區</name>
</city>
<city>
<name>昌平區</name>
</city>
</province>
<province name="山東省">
<city>
<name>濟南</name>
</city>
<city>
<name>青島</name>
</city>
</province>
</china>
END.