最近在项目中遇到了JAVA bean 和XML互转的需求, 本来准备循规蹈矩使用dom4j忽然想起来之前曾接触过的XStream, 一番研究豁然开朗,利器啊利器, 下来就XStream的一些用法与大家分享。
XStream是大名鼎鼎的thought works下的一个开源项目, 主要功能是提供JAVA bean 和XML文本之间的转换,另外还提供JAVA bean和JSON之间的转换,这个不在本次讨论的范围内。
XStream进行转换是非常简单的,对JAVA bean没有任何要求:
package xstreamTest;
public class Person {
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
转换代码是这样的:
XStream xstream = new XStream();
Person person = new Person();
person.setName("pli");
person.setAge(18);
System.out.println(xstream.toXML(person));
我们得到了这样的结果:
pli
18
package xstreamTest;
@XStreamAlias("person")
public class Person {
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
而执行代码会变成这样:
XStream xstream = new XStream();
xstream.autodetectAnnotations(true);
Person person = new Person();
person.setName("pli");
person.setAge(18);
System.out.println(xstream.toXML(person));
pli
18
@XStreamAlias("person")
public class Person {
private String name;
@XStreamAsAttribute
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
pli
好玩吧。
@XStreamAlias("person")
public class Person {
private String name;
@XStreamAsAttribute
private int age;
List girlFriends;
public List getGirlFriends() {
return girlFriends;
}
public void setGirlFriends(List girlFriends) {
this.girlFriends = girlFriends;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
pli
YuanYuanGao
QiShu
BoZhiZhang
结果其实也不赖,XStream在这里提供了一个@XStreamImplicit(itemFieldName=***)的annotation来满足用户想将List的根节点去掉和改变列表名字的需求,对应到我们的例子上就是去掉@XStreamAlias("person")
public class Person {
private String name;
@XStreamAsAttribute
private int age;
@XStreamImplicit(itemFieldName="girl")
List girlFriends;
public List getGirlFriends() {
return girlFriends;
}
public void setGirlFriends(List girlFriends) {
this.girlFriends = girlFriends;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
pli
YuanYuanGao
QiShu
BoZhiZhang
@XStreamAlias("person")
public class Person {
private String name;
@XStreamAsAttribute
private int age;
@XStreamImplicit(itemFieldName="girl")
@XStreamOmitField
List girlFriends;
public List getGirlFriends() {
return girlFriends;
}
public void setGirlFriends(List girlFriends) {
this.girlFriends = girlFriends;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
pli
@XStreamAlias("person")
public class Person {
private String name;
@XStreamAsAttribute
private int age;
@XStreamImplicit(itemFieldName="girl")
@XStreamOmitField
List girlFriends;
Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public List getGirlFriends() {
return girlFriends;
}
public void setGirlFriends(List girlFriends) {
this.girlFriends = girlFriends;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
pli
2012-08-04 04:35:01.857 UTC
public class DateConverter implements Converter {
@Override
public boolean canConvert(Class clazz) {
return (Date.class).equals(clazz);
}
@Override
public void marshal(Object object, HierarchicalStreamWriter writer,
MarshallingContext context) {
Date date = (Date) object;
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");
writer.setValue(format.format(calendar.getTime()));
}
@Override
public Object unmarshal(HierarchicalStreamReader arg0,
UnmarshallingContext arg1) {
return null;
}
}
@XStreamAlias("person")
public class Person {
private String name;
@XStreamAsAttribute
private int age;
@XStreamImplicit(itemFieldName="girl")
@XStreamOmitField
List girlFriends;
@XStreamConverter(value=DateConverter.class)
Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public List getGirlFriends() {
return girlFriends;
}
public void setGirlFriends(List girlFriends) {
this.girlFriends = girlFriends;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
pli
2012-50-04
@XStreamAlias("person")
public class Person {
private String name = "pli";
@XStreamAsAttribute
private int age = 19;
@XStreamImplicit(itemFieldName="girl")
@XStreamOmitField
List girlFriends;
@XStreamConverter(value=DateConverter.class)
Date birthday = new Date();
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public List getGirlFriends() {
return girlFriends;
}
public void setGirlFriends(List girlFriends) {
this.girlFriends = girlFriends;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
pli
2012-36-04
girlFriends这个属性压根就没有被序列化,其实我是想让它序列化成这个样子:
pli
2012-36-04