Xstream是一个解决Object与XML之间互相转换的开源项目,以下是官网,英文版http://xstream.codehaus.org/
官方首页的使用介绍很简单,
假如我们有一个Person类
public class Person {
private String firstname;
private String lastname;
private PhoneNumber phone;
private PhoneNumber fax;
// ... constructors and methods
}
public class PhoneNumber {
private int code;
private String number;
// ... constructors and methods
}
在我们下载完Xstream的类库并导入项目之后,就可以这么使用了
Person joe = new Person("Joe", "Walnes");
joe.setPhone(new PhoneNumber(123, "1234-456"));
joe.setFax(new PhoneNumber(123, "9999-999"));
Xstream xstream = new Xstream();
String xml = xstream.toXML(joe);
<pre code_snippet_id="284188" snippet_file_name="blog_20140410_2_1998239">
<person> <firstname>Joe</firstname> <lastname>Walnes</lastname> <phone> <code>123</code> <number>1234-456</number> </phone> <fax> <code>123</code> <number>9999-999</number> </fax> </person>
如果想转换成对象只需要:
Person person = (Person)xstream.fromXML(xml);
但是,这只是最简单的普通应用,XML在我们真实的项目中所扮演的角色是举足轻重的,
会是configuration, request, response更有甚者,可能是我们的一个项目例如soapui。
所以xml是很复杂的,当其中存在两个对象同时引用了一个引用会怎么样呢。
Person joe = new Person("Joe", "Walnes");
joe.setPhone(new PhoneNumber(123, "1234-456"));
joe.setFax(new PhoneNumber(123, "9999-999"));
Person jack = joe;
List<Person> list = new ArrayList<Person>();
list.add(joe);
list.add(jack);
Xstream xstream = new Xstream();
String xml = xstream.toXML(jack);
最后xml的结果会是什么呢,我们发现是这样的:
<list>
<com.freud.test.Person>
<firstname>Joe</firstname>
<lastname>Walnes</lastname>
<phone>
<code>123</code>
<number>1234-456</number>
</phone>
<fax>
<code>123</code>
<number>9999-999</number>
</fax>
</com.freud.test.Person>
<com.freud.test.Person reference="../com.freud.test.Person"/>
</list>
我们会发现红色的jack这一个对象并没有真正的打印出来,而是引用了joe对象。
仔细翻阅XStream的API你会发现,在Xstream初始化之后又这么一个方法。
xstream.setMode(int Mode);
其中Mode可以为:
XStream.XPATH_RELATIVE_REFERENCES; -- by default 这是一个集成了W3C的XPATH标准的相对引用路径
XStream.XPATH_ABSOLUTE_REFERENCES; -- 集成了W3C的XPATH标准的绝对引用路径
XStream.SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES; -- 单个节点的绝对引用路径(符合W3C的XPATH标准)
XStream.SINGLE_NODE_XPATH_RELATIVE_REFERENCES; -- 单个节点的相对引用路径(符合W3C的XPATH标准)
XStream.ID_REFERENCES; -- id属性引用,如果节点的attribute 中有id这一项的话,才可以使用了
XStream.NO_REFERENCES; -- 没有引用
通常我们经常用的是第一个默认,和最后一个无引用。默认的结果就是上述例子的结果,这样有什么坏处呢,
当你把XML的字符串重新组装成对象的时候,如果对象够复杂并且Map中有list加对象,有时候,你会发现,就会报错。
这就是Xstream自己对自己装箱拆箱的不完善。我在项目中遇到一次,自己再写例子尝试的时候竟然无法重现,碍于项目代码不能共享,
不写代码了。
我的解决方案当然就是最笨的办法,在初始化的时候,
xstream.setMode(XStream.NO_REFERENCES);
这样问题就没有那么麻烦,但相对来说我们增加了String的长度,增大了内存的占用,也就加大了运行的时间,从效率来讲是不合适的。
reference topic from official doc:
http://xstream.codehaus.org/graphs.html