XStream是一个将对象序列化为xml并解析xml为对象的框架,主页位于http://xstream.codehaus.org。使用非常简单
引入依赖:
- <dependency>
- groupId>com.thoughtworks.xstream</artifactId>xstreamversion>1.4.2>
需要的依赖
XmlPull一个xmlpull parser api用来判断具体的xml解析实现(DOM、StAX等)工厂
其他可供选择的Xpp3、DOM4J
1、创建待序列化的对象:
Person.java
publicclassPerson{
-
- privateIntegerid;
- privateStringusername;
- privateStringpassword;
- privateAddressaddress;
- ...
- }
Person中包含一个Address作为Field
classAddress{
privateStringstreet;
privateStringcity;
......
}
2、序列化和反序列化
使用XStream只需要实例化一个XStream对象即可:
XStreamxstream=newXStream();
或者采用DOM的方式解析:
newXStream(newDomDriver());
//此时不需要XPP3
或者基于事件的StAX
newStaxDriver());
//如果采用Java6,也不需要xpp3.将采用默认的JAXB
//对象序列化为xml
xstream.toXML(Object)
//xml反序列化为对象
xstream.fromXML(xml)
一个例子:
Personp=newPerson();
p.setId(1);
p.setUsername("robin");
p.setPassword("123");
p.setAddress(newAddress("xxRoad","chengdu"));
xstream.toXML(p);
输出为:
org.java.codelib.xstream.Personid>1username>robinpassword>123addressstreet>xxRoadcity>chengdu>
3、alias
这里可以看到生成的xml中root element名字为class,如果需要修改就需要用到
xstream.alias("person",Person.class);
这样就会用person替代org.java.codelib.xstream.Person
同样对于field也可以使用alias:
xstream.aliasField("personId",85); font-weight:bold">class,"id");
这样就会将Person中的id替换为<personId>1</personId>
其他的还有aliasAttribute即将field作为attribute时并采用别名,当前前提是需要设置field作为attribute:
class);
xstream.useAttributeFor(Person."id");
xstream.aliasAttribute("personId",250); line-height:18px"> xstream.toXML(p);
输出为:
<?xmlversion="1.0"?>personpersonId="1">person>
说到设置field作为attribute如果field是一个自定义对象,或者需要将Date之类的属性格式化输出,如本例中的Address该如何处理?这就是另外一个话题
需要说明的是以上在序列化为xml的时候使用了alias,那么在反序列化的时候同样需要这些相应的代码,不然可能会抛出UnknownFieldException
4、convertors
convertor的作用是在做序列化或反序列化的时候,将对象中的属性按照特定的形式输出或转化,在XStream 中默认初始化了大量的必要convertors,见http://xstream.codehaus.org/converters.html 或者在XStream.java中有方法setupConverters()。
自定义一个convertor需要两步:
1、实现Converter接口及相关方法:
classDateConverterimplementsConverter{
@Override
booleancanConvert(Classtype){
returntype.equals(Date. }
voidmarshal(Objectsource,HierarchicalStreamWriterwriter,MarshallingContextcontext){
DateFormatdateFormat=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss");
writer.setValue(dateFormat.format((Date)source));
publicObjectunmarshal(HierarchicalStreamReaderreader,UnmarshallingContextcontext){
try{
returndateFormat.parse(reader.getValue());
}catch(ParseExceptione){
e.printStackTrace();
returnnull;
}
2、在xstream中注册该convertor:
xstream.registerConverter(newDateConverter());
输出
birthday>2013-02-1715:12:53>
当然,xstream针对Date也做了默认的实现,只不过默认输出为UTC格式
现在我们回到上面的问题,即将对象Address作为Person的属性,下面是一个convertor的实现:
classPersonConverter@SuppressWarnings("rawtypes")
returntype.equals(Person. Personperson=(Person)source;
if(person!=null){
Addressaddress=person.getAddress();
if(address!=if(StringUtils.isNotBlank(address.getStreet())){
writer.addAttribute("street",address.getStreet());
if(StringUtils.isNotBlank(address.getCity())){
writer.addAttribute("city",address.getCity());
//address
if(person.getBirthday()!= writer.startNode("birthday");
context.convertAnother(person.getBirthday(),newDateConverter());
writer.endNode();
//username
if(person.getUsername()!= writer.startNode("username");
context.convertAnother(person.getUsername());
//otherfields
Addressaddress=newAddress();
address.setCity(reader.getAttribute("city"));
address.setStreet(reader.getAttribute("street"));
p.setAddress(address);
while(reader.hasMoreChildren()){
reader.moveDown();
if("birthday".equals(reader.getNodeName())){
Datedate=(Date)context.convertAnother(p,Date. p.setBirthday(date);
elseif("username".equals(reader.getNodeName())){
p.setUsername((String)context.convertAnother(p,String.class));
reader.moveUp();
returnp;
}
其中序列化时输出:
personstreet="xxRoad"city="chengdu">2013-02-1716:34:24>
当然如果作为fields的对象只有一个属性就简单得多了,在http://xstream.codehaus.org/alias-tutorial.html#attributes有例子可供参考
5、implicitCollections
考虑Person有列表属性:
privateList<Address>addresses;
在序列化为xml时:
addresses>road_1>road_2>
当然有时候并不想要addresses,这就是XStream中的implicitCollections:对集合的属性在序列化是不想显示roottag。值需要很简单的处理:
xstream.alias("address",Address. xstream.addImplicitCollection(Person."addresses");
returnxstream.toXML(formatPerson());
输出为:
6、annotation
以上说的内容都支持annotation:
@XStreamAlias("person")
@XStreamAlias("personId")
@XStreamAsAttribute
@XStreamConverter(DateConverter.class)
privateDatebirthday;
@XStreamImplicit(itemFieldName="address")
privateList<Address>addresses;
}
}
需要加上autodetectAnnotations(true)
xstream.autodetectAnnotations(true);
returnxstream.toXML(p);
输出:
>2013-02-1717:08:00addressstreet="road_1"city="chengdu"addressstreet="road_2"city="chengdu">
7、其他
xstream提供了对json的解析以及持久化(文件系统)的支持,这里就不再介绍了