xstream简单实用

XStream是一个将对象序列化为xml并解析xml为对象的框架,主页位于http://xstream.codehaus.org。使用非常简单

引入依赖:

Xml代码
  1. <dependency>
  2. groupId>com.thoughtworks.xstream</artifactId>xstreamversion>1.4.2>

需要的依赖

XmlPull一个xmlpull parser api用来判断具体的xml解析实现(DOM、StAX等)工厂

其他可供选择的Xpp3DOM4J

1、创建待序列化的对象:

Person.java

Java代码
    publicclassPerson{
  1. privateIntegerid;
  2. privateStringusername;
  3. privateStringpassword;
  4. privateAddressaddress;
  5. ...
  6. }

Person中包含一个Address作为Field

classAddress{
  • privateStringstreet;
  • privateStringcity;
  • ......
  • }
  • 2、序列化和反序列化

    使用XStream只需要实例化一个XStream对象即可:

    XStreamxstream=newXStream();
  • //采用这个构造器认需要依赖:xstream-[version].jar,xpp3-[version].jarandxmlpull-[version].jar
  • 或者采用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的解析以及持久化(文件系统)的支持,这里就不再介绍了

    相关文章

    php输出xml格式字符串
    J2ME Mobile 3D入门教程系列文章之一
    XML轻松学习手册
    XML入门的常见问题(一)
    XML入门的常见问题(三)
    XML轻松学习手册(2)XML概念