开源dom框架xStream转换器(Converter)的基本用法

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>
 

https://blog.csdn.net/misakic52/article/details/42919123

猜你喜欢

转载自blog.csdn.net/qb170217/article/details/81867679