XStream是Java类库,用来将对象序列化成XML (JSON)或反序列化为对象。
也就是说,使用XStream,我们可以把Java对象转换成XML,也可以将XML转换为Java对象。
XStream的必导JAR包:
为了演示我们的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>dongchengqudescription>
com.veeja.demo.City>
<com.veeja.demo.City>
<name>昌平区name>
<description>changpingqudescription>
com.veeja.demo.City>
cities>
com.veeja.demo.Province>
<com.veeja.demo.Province>
<name>山东省name>
<cities>
<com.veeja.demo.City>
<name>济南name>
<description>jinandescription>
com.veeja.demo.City>
<com.veeja.demo.City>
<name>青岛name>
<description>qingdaodescription>
com.veeja.demo.City>
cities>
com.veeja.demo.Province>
list>
我们可以观察一下这个结果:
我们可以明显的看出来,这是一个XML格式的文本。
根元素是, 因为我们是把List对象转换为xml,所以根元素为
。
第二级为,因为我们Javabean的类型为Province,所以元素的名称就是类的完整名
第三级为和 ,就是Province类内的属性名。
我们在上面生成的xml中,发现了几个问题:
- 根元素是
,根据我们的需求,其实这个根元素如果是
更合适一点。 - 还有中间的
,都太长了,而且还有类的包名,这里可以简要一些,换成小写,也就是 就可以了。
这个问题怎么解决呢?答案是使用 别名(alias)。
我们有这么几个需求:
我们可以使用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>dongchengqudescription>
city>
<city>
<name>昌平区name>
<description>changpingqudescription>
city>
cities>
province>
<province>
<name>山东省name>
<cities>
<city>
<name>济南name>
<description>jinandescription>
city>
<city>
<name>青岛name>
<description>qingdaodescription>
city>
cities>
province>
china>
我们现在不妨把山东省的那一部分单独拿出来看一看:
<province>
<name>山东省name>
<cities>
<city>
<name>济南name>
<description>jinandescription>
city>
<city>
<name>青岛name>
<description>qingdaodescription>
city>
cities>
province>
首先,我觉得中间的一个cities标签没有什么必要,完全可以去掉,而且name标签,完全可以作为province的一个name属性,而没有必要单独生成一个子元素。
也就是经过处理,如果可以得到这样的形式:
<province name="山东省">
<city>
<name>济南name>
<description>jinandescription>
city>
<city>
<name>青岛name>
<description>qingdaodescription>
city>
province>
这样就会简洁的多。
也就是说,默认情况下,Javabean的属性都会生成子元素,但是我们希望生成为元素的属性。
xstream.useAttributeFor(Ccc.class, "name");
来将Ccc类的name属性,生成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>dongchengqudescription>
city>
<city>
<name>昌平区name>
<description>changpingqudescription>
city>
province>
<province name="山东省">
<city>
<name>济南name>
<description>jinandescription>
city>
<city>
<name>青岛name>
<description>qingdaodescription>
city>
province>
china>
我们又发现了一个问题,这个
这个时候,我们可以使用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.