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确实是一个很强大的工具。我也是最近来接触到,刚开始学习,文章里必定也有不少不合理的地方,希望大家一起相互学习。



Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐