xstream处理null值属性转换

日常使用xstream进行xml转换的时候,会遇到实体对象中有null值的情况,默认的xstream转换遇见null值后不会生成节点xml信息,但是一般为了保证我们xml的可读和完整性,我们希望即使是null值也能够输出节点的xml,废话不说,上干货。

两个实体类:

/**
 * Project Name:test
 * File Name:User.java
 * Package Name:dao
 * Date:2014-5-16下午5:11:41
 * Copyright (c) 2014, renxingchen All Rights Reserved.
 *
 */

package dao;

import java.util.List;
import java.util.Set;

/**
 * @ClassName: User
 * @description: TODO ADD FUNCTION.
 * @date: 2014-5-16 下午5:11:41
 * 
 * @author renxingchen
 * @since JDK 1.6
 */
public class User {
	public User() {

	}

	public User(int id, String name, List orderList, Order order,
			Set orderSet) {
		super();
		this.id = id;
		this.name = name;
		this.orderList = orderList;
		this.order = order;
		this.orderSet = orderSet;
	}

	private int id;
	private String name;
	private List orderList;
	private Order order;
	private Set orderSet;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Order getOrder() {
		return order;
	}

	public void setOrder(Order order) {
		this.order = order;
	}

	public List getOrderList() {
		return orderList;
	}

	public void setOrderList(List orderList) {
		this.orderList = orderList;
	}

	public Set getOrderSet() {
		return orderSet;
	}

	public void setOrderSet(Set orderSet) {
		this.orderSet = orderSet;
	}

}

/**
 * Project Name:test
 * File Name:Order.java
 * Package Name:dao
 * Date:2014-5-16下午5:11:41
 * Copyright (c) 2014, renxingchen All Rights Reserved.
 *
 */

package dao;

/**
 * @ClassName: Order
 * @description: TODO ADD FUNCTION.
 * @date: 2014-5-16 下午5:13:09
 * 
 * @author renxingchen
 * @since JDK 1.6
 */
public class Order {

	public Order() {

	}

	public Order(int id, String orderName) {
		super();
		this.id = id;
		this.orderName = orderName;
	}

	private int id;
	private String orderName;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getOrderName() {
		return orderName;
	}

	public void setOrderName(String orderName) {
		this.orderName = orderName;
	}

}

自己的xstream转换器,目前可以处理包含Collection集合的对象,如果在实际使用中无法满足需求,可以对marshalSuper这个方法进行拓展即可。

/**
 * Project Name:test
 * File Name:MoreDataResultNullConverter.java
 * Package Name:dao
 * Date:2014-5-16下午5:11:41
 * Copyright (c) 2014, renxingchen All Rights Reserved.
 *
 */

package dao;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;

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;

/**
 * 
 * @ClassName: MoreDataResultNullConverter
 * @description: 处理含有null值对象的xstream转换器
 * @date: 2014-5-19 下午6:05:12
 * 
 * @author renxingchen
 * @since JDK 1.6
 */
public class MoreDataResultNullConverter implements Converter {

	@SuppressWarnings("rawtypes")
	private Class currentType;
	private final String clazzNames[] = { "User", "Order" };// 定义所要转换的对象及所包含的对象名称
	private List clazzNamesList;

	@SuppressWarnings("rawtypes")
	@Override
	public boolean canConvert(Class type) {
		currentType = type;
		clazzNamesList = Arrays.asList(clazzNames);
		if (clazzNamesList.contains(currentType.getSimpleName())) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public void marshal(Object source, HierarchicalStreamWriter writer,
			MarshallingContext context) {
		try {
			marshalSuper(source, writer, context, currentType);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private Object getObj(Class clazz, String nodeName, Object source)
			throws Exception {
		Method method = clazz.getMethod("get"
				+ Character
						.toUpperCase(nodeName.substring(0, 1).toCharArray()[0])
				+ nodeName.substring(1));
		Object obj = null;
		obj = method.invoke(clazz.cast(source), new Object[0]);
		return obj;
	}

	@SuppressWarnings({ "rawtypes" })
	private void objConverter(Object source, HierarchicalStreamWriter writer,
			MarshallingContext context, Class clazz, String nodeName,
			Class fieldClazz) throws Exception {
		Object obj = getObj(clazz, nodeName, source);
		writer.startNode(nodeName);
		marshalSuper(obj, writer, context, fieldClazz);
		writer.endNode();
	}

	@SuppressWarnings({ "rawtypes" })
	private void collectionConverter(Object source,
			HierarchicalStreamWriter writer, MarshallingContext context,
			Class clazz, String nodeName, Field field) throws Exception {
		Type types[] = ((ParameterizedType) field.getGenericType())
				.getActualTypeArguments();
		Object obj = getObj(clazz, nodeName, source);
		Collection collection = null;
		if (field.getType().equals(List.class)) {
			collection = (List) obj;
		} else if (field.getType().equals(Set.class)) {
			collection = (Set) obj;
		}
		writer.startNode(nodeName);
		for (Object object : collection) {
			String clazzName = ((Class) types[0]).getSimpleName();
			writer.startNode(Character.toLowerCase(clazzName.substring(0, 1)
					.toCharArray()[0]) + clazzName.substring(1));
			marshalSuper(object, writer, context, (Class) types[0]);
			writer.endNode();
		}
		writer.endNode();
	}

	@SuppressWarnings({ "rawtypes" })
	private void basicTypeConverter(Object source,
			HierarchicalStreamWriter writer, MarshallingContext context,
			Class clazz, String nodeName) throws Exception {
		Object obj = getObj(clazz, nodeName, source);
		writer.startNode(nodeName);
		writer.setValue(obj == null ? "" : obj.toString());
		writer.endNode();
	}

	@SuppressWarnings({ "rawtypes" })
	private void marshalSuper(Object source, HierarchicalStreamWriter writer,
			MarshallingContext context, Class clazz) throws Exception {
		Field fields[] = clazz.getDeclaredFields();
		for (Field field : fields) {
			String nodeName = field.getName();
			Class fieldClazz = field.getType();
			if (clazzNamesList.contains(fieldClazz.getSimpleName())) {
				objConverter(source, writer, context, clazz, nodeName,
						fieldClazz);
			} else if (Arrays.asList(fieldClazz.getInterfaces()).contains(
					Collection.class)) {
				collectionConverter(source, writer, context, clazz, nodeName,
						field);
			} else {
				basicTypeConverter(source, writer, context, clazz, nodeName);
			}
		}
	}

	@Override
	public Object unmarshal(HierarchicalStreamReader reader,
			UnmarshallingContext context) {
		// TODO Auto-generated method stub
		return null;
	}

}

最后是测试类:

/**
 * Project Name:wisdom-tourism
 * File Name:Demo.java
 * Package Name:dao
 * Date:2014-5-16下午5:11:20
 * Copyright (c) 2014, renxingchen All Rights Reserved.
 *
 */

package dao;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.StaxDriver;

/**
 * ClassName:Demo 
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2014-5-16 下午5:11:20
* * @author jason * @version * @since JDK 1.6 * @see */ public class Demo { public static void main(String[] args) { Order order = new Order(1, null); Order order1 = new Order(2, null); List orderList = new ArrayList(); Set orderSet = new HashSet(); orderList.add(order); orderList.add(order1); orderSet.add(order); orderSet.add(order1); User user = new User(1, null, orderList, order, orderSet); XStream xStream = new XStream(new StaxDriver()); xStream.alias("user", User.class); xStream.registerConverter(new MoreDataResultNullConverter()); String result = xStream.toXML(user); System.err.println(result); } }

测试结果:


	1
	
	
		
			1
			
		
		
			2
			
		
	
	
		1
		
	
	
		
			1
			
		
		
			2
			
		
	

null值属性的节点能够被输出。

仓促写成,应该还有很多问题,如果有疑问请留言交流。

你可能感兴趣的:(java基础)