您的位置:首页 > 其它

xstream简单实用

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

引入依赖:

Xml代码


<dependency>

<groupId>com.thoughtworks.xstream</groupId>

<artifactId>xstream</artifactId>

<version>1.4.2</version>

</dependency>

需要的依赖

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

其他可供选择的Xpp3DOM4J

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

Person.java

Java代码


public class Person {

private Integer id;

private String username;

private String password;

private Address address;

...

}

Person中包含一个Address作为Field

Java代码


public class Address {

private String street;

private String city;

......

}

2、序列化和反序列化

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

Java代码


XStream xstream = new XStream();

//采用这个构造器默认需要依赖:xstream-[version].jar, xpp3-[version].jar and xmlpull-[version].jar

或者采用DOM的方式解析:

Java代码


XStream xstream = new XStream(new DomDriver());

//此时不需要XPP3

或者基于事件的StAX

Java代码


XStream xstream = new XStream(new StaxDriver());

//如果采用Java 6,也不需要xpp3.将采用默认的JAXB

Java代码


//对象序列化为xml

xstream.toXML(Object)

//xml反序列化为对象

xstream.fromXML(xml)

一个例子:

Java代码


Person p = new Person();

p.setId(1);

p.setUsername("robin");

p.setPassword("123");

p.setAddress(new Address("xxRoad", "chengdu"));

xstream.toXML(p);

输出为:

Xml代码


<org.java.codelib.xstream.Person>

<id>1</id>

<username>robin</username>

<password>123</password>

<address>

<street>xxRoad</street>

<city>chengdu</city>

</address>

</org.java.codelib.xstream.Person>

3、alias

这里可以看到生成的xml中root element名字为class,如果需要修改就需要用到

Java代码


xstream.alias("person", Person.class);

这样就会用person替代org.java.codelib.xstream.Person

同样对于field也可以使用alias:

Java代码


xstream.aliasField("personId", Person.class, "id");

这样就会将Person中的id替换为<personId>1</personId>

其他的还有aliasAttribute即将field作为attribute时并采用别名,当前前提是需要设置field作为attribute:

Java代码


XStream xstream = new XStream(new StaxDriver());

xstream.alias("person", Person.class);

xstream.useAttributeFor(Person.class, "id");

xstream.aliasAttribute("personId", "id");

xstream.toXML(p);

输出为:

Xml代码


<?xml version="1.0" ?><person personId="1"><username>robin</username><password>123</password><address><street>xxRoad</street><city>chengdu</city></address></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接口及相关方法:

Java代码


public class DateConverter implements Converter {

@Override

public boolean canConvert(Class type) {

return type.equals(Date.class);

}

@Override

public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

writer.setValue(dateFormat.format((Date) source));

}

@Override

public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

try {

return dateFormat.parse(reader.getValue());

} catch (ParseException e) {

e.printStackTrace();

}

return null;

}

}

2、在xstream中注册该convertor:

Java代码


xstream.registerConverter(new DateConverter());

输出

Xml代码


<?xml version="1.0" ?><person><id>1</id><username>robin</username><password>123</password><birthday>2013-02-17 15:12:53</birthday><address><street>xxRoad</street><city>chengdu</city></address></person>

当然,xstream针对Date也做了默认的实现,只不过默认输出为UTC格式

现在我们回到上面的问题,即将对象Address作为Person的属性,下面是一个convertor的实现:

Java代码


public class PersonConverter implements Converter {

@SuppressWarnings("rawtypes")

@Override

public boolean canConvert(Class type) {

return type.equals(Person.class);

}

@Override

public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {

Person person = (Person) source;

if (person != null) {

Address address = person.getAddress();

if (address != null) {

if (StringUtils.isNotBlank(address.getStreet())) {

writer.addAttribute("street", address.getStreet());

}

if (StringUtils.isNotBlank(address.getCity())) {

writer.addAttribute("city", address.getCity());

}

}

//address

if (person.getBirthday() != null) {

writer.startNode("birthday");

context.convertAnother(person.getBirthday(), new DateConverter());

writer.endNode();

}

//username

if (person.getUsername() != null) {

writer.startNode("username");

context.convertAnother(person.getUsername());

writer.endNode();

}

//other fields

}

}

@Override

public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {

Person p = new Person();

Address address = new Address();

address.setCity(reader.getAttribute("city"));

address.setStreet(reader.getAttribute("street"));

p.setAddress(address);

while (reader.hasMoreChildren()) {

reader.moveDown();

if ("birthday".equals(reader.getNodeName())) {

Date date = (Date) context.convertAnother(p, Date.class, new DateConverter());

p.setBirthday(date);

} else if ("username".equals(reader.getNodeName())) {

p.setUsername((String) context.convertAnother(p, String.class));

}

//other fields

reader.moveUp();

}

return p;

}

}

其中序列化时输出:

Xml代码


<?xml version="1.0" ?><person street="xxRoad" city="chengdu"><birthday>2013-02-17 16:34:24</birthday><username>robin</username></person>

当然如果作为fields的对象只有一个属性就简单得多了,在http://xstream.codehaus.org/alias-tutorial.html#attributes有例子可供参考

5、implicitCollections

考虑Person有列表属性:

Java代码


private List<Address> addresses;

在序列化为xml时:

Xml代码


<?xml version="1.0" ?><person><addresses><address><street>road_1</street><city>chengdu</city></address><address><street>road_2</street><city>chengdu</city></address></addresses></person>

当然有时候并不想要addresses,这就是XStream中的implicitCollections:对集合的属性在序列化是不想显示roottag。值需要很简单的处理:

Java代码


XStream xstream = new XStream(new StaxDriver());

xstream.alias("person", Person.class);

xstream.alias("address", Address.class);

xstream.addImplicitCollection(Person.class, "addresses");

return xstream.toXML(formatPerson());

输出为:

Xml代码


<?xml version="1.0" ?><person><address><street>road_1</street><city>chengdu</city></address><address><street>road_2</street><city>chengdu</city></address></person>

6、annotation

以上说的内容都支持annotation:

Java代码


@XStreamAlias("person")

public class Person {

@XStreamAlias("personId")

@XStreamAsAttribute

private Integer id;

private String username;

private String password;

@XStreamConverter(DateConverter.class)

private Date birthday;

private Address address;

@XStreamImplicit(itemFieldName = "address")

private List<Address> addresses;

}

Java代码


@XStreamAlias("person")

public class Address {

@XStreamAsAttribute

private String street;

@XStreamAsAttribute

private String city;

}

需要加上autodetectAnnotations(true)

Java代码


XStream xstream = new XStream(new StaxDriver());

xstream.autodetectAnnotations(true);

return xstream.toXML(p);

输出:

Xml代码


<?xml version="1.0" ?><person personId="1"><username>robin</username><password>123</password><birthday>2013-02-17 17:08:00</birthday><address street="road_1" city="chengdu"></address><address street="road_2" city="chengdu"></address></person>

7、其他

xstream提供了对json的解析以及持久化(文件系统)的支持,这里就不再介绍了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: