xStream是一种可以对java对象与xml、json相互转换的工具。基本用法很简单,网上类似的教程很有很多。今天,我在这里所提到的是xStream中的转换器(Converter)的用法。
converter可以自定义转换设置,针对自己的不同的特殊需求指定不同的规则。
本文测试用到的测试对象为:
package pojo;
import java.sql.Timestamp;
public class Person {
private String name;
private Timestamp date;
//getter and setter
}
注册一个转换器需要实现
com.thoughtworks.xstream.converters.Converter;
的接口,这个接口有三个需要实现的方法:
package converter;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class CommonConverter implements Converter {
@Override
public boolean canConvert(Class arg0) {
// TODO Auto-generated method stub
return false;
}
@Override
public void marshal(Object arg0, HierarchicalStreamWriter arg1,
MarshallingContext arg2) {
// TODO Auto-generated method stub
}
@Override
public Object unmarshal(HierarchicalStreamReader arg0,
UnmarshallingContext arg1) {
// TODO Auto-generated method stub
return null;
}
}
1.其中canConvert()用来判断需要序列化的对象是否使用此转换器,用户可以在此方法自定义使用的类,或者可以直接返回true来表名此转换器为通用。xstream会自动执行此方法,如果canConvert()的返回结果为false,转换器将不起作用。
2.marshal()序列化,对于java对象转换成xml文件的自定义序列化操作将会执行此方法。方法含有三个参数,分别是:需要转换的对象、序列化输出对象和序列化上下文对象。
3.unmarshal()反序列化,对于xml文件转换成java对象是需要执行的方法。方法含有两个参数,分别是:反序列化读取对象和反序列化上下文对象。
对于marshal()的使用方法如下:
第一个参数就是需要转换的java对象,HierarchicalStreamWriter有几个常用的方法:
startNode(String name)和endNode()作为一对出现的方法,可以输出一个dom节点,startNode(String name)包含一个参数,即节点的名称。PS:要记住!当你开启一个节点的时候切记一定要在你不用的时候关掉他,确保他们是一对一对出现的,就像xml标签一样。
addAttribute(String name,String value)顾名思义,此方法可以定义节点的属性和属性的值,第一个参数定义属性名称,第二个参数定义属性的值。
setValue(String text)方法定义节点的text属性,参数为text的值。
注意:就像之前提到的那样,addAttribute和setValue写在哪一对startNode和endNode中间,他就定义是哪个节点的属性和值。
下面举个简单的例子,
测试方法为:
package testpackage;
import java.sql.Timestamp;
import java.util.Date;
import pojo.Person;
import com.thoughtworks.xstream.XStream;
import converter.CommonConverter;
public class Convert {
private XStream xstream = null;
private Person person = null;
public void init() {
try {
xstream = new XStream();
} catch (Exception e) {
e.printStackTrace();
}
person = new Person();
person.setDate(new Timestamp(new Date().getTime()));
person.setName("j,a,v,a");
}
public void convert(){
xstream.alias("person", Person.class); //修改类名
xstream.registerConverter(new CommonConverter()); //注册转换器
System.out.println(xstream.toXML(person));
}
public static void main(String[] args){
Convert c = new Convert();
c.init();
c.convert();
}
}
转换器的代码如下:
package converter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import pojo.Person;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class CommonConverter implements Converter {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public boolean canConvert(Class arg0) {
// TODO Auto-generated method stub
return arg0.equals(Person.class);
}
@Override
public void marshal(Object arg0, HierarchicalStreamWriter arg1,
MarshallingContext arg2) {
Person p = (Person) arg0;
arg1.startNode("name");
arg1.addAttribute("name", p.getName()); //所有关于name的属性都要写在startNode和endNode之前
arg1.endNode(); //写完一个节点之后切记要关掉
arg1.startNode("date");
arg1.setValue(format.format(p.getDate())); //格式化日期格式
arg1.endNode();
}
@Override
public Object unmarshal(HierarchicalStreamReader arg0,
UnmarshallingContext arg1) {
// TODO Auto-generated method stub
return null;
}
}
此方法只适合Person类,而且执行java对象转换xml时会执行marshal方法,生成自定义的xml文件。执行main函数打印的xml为:
<person>
<name name="j,a,v,a"/>
<date>2015-01-20 16:27:49</date>
</person>
可以看到,由于我在转换器中将name的值定义为了name节点的一个属性,而且把日期类型按照自定义的格式转换。
上面只是一些最基本的用法,对于一些属性很多的对象,在这里可以利用java的反射来自动输出,对于我们特定的需求的再对特定的属性进行特殊处理。比如在我最近开发的项目中就有类似的需求,我也是刚刚接触这个工具,自己写了一个简单的转换器来测试自己的理解是否正确,我自己的测试转换器如下:
package testpackage;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import pojo.User;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class UserConverter implements Converter {
@Override
public boolean canConvert(Class arg0) {
// TODO Auto-generated method stub
return true;
}
@Override
public void marshal(Object arg0, HierarchicalStreamWriter arg1,
MarshallingContext arg2) {
try {
Field[] fields = arg0.getClass().getDeclaredFields();
for(Field field : fields){
field.setAccessible(true);
String fieldName = field.getName();
if(fieldName.equals("name")){
String[] bits = field.get(arg0).toString().split(",");
arg1.startNode("name");
for(String bit : bits){
arg1.startNode("bit");
arg1.setValue(bit);
arg1.endNode();
}
arg1.endNode();
}else if(field.getType().getName().equals("java.sql.Timestamp")){
Timestamp ts = (Timestamp)field.get(arg0);
arg1.startNode(field.getName());
arg1.setValue(ts.getTime() + "");
arg1.endNode();
}else{
arg1.startNode(field.getName());
if(field.get(arg0)==null||field.get(arg0).toString().equals("")){
}else{
arg1.setValue(field.get(arg0).toString());
}
arg1.endNode();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object unmarshal(HierarchicalStreamReader arg0,
UnmarshallingContext arg1) {
/*User user = new User();
arg0.moveDown();
user.setName(arg0.getValue());
arg0.moveUp();
return user;*/
return null;
}
}
这是个共用的转换器,对于同样的Person对象,这个转换器生成的xml文件如下:
<person>
<name>
<bit>j</bit>
<bit>a</bit>
<bit>v</bit>
<bit>a</bit>
</name>
<date>1421743107182</date>
</person>
xStream确实是一个很强大的工具。我也是最近来接触到,刚开始学习,文章里必定也有不少不合理的地方,希望大家一起相互学习。