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<Order> orderList, Order order,
			Set<Order> 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<Order> orderList;
	private Order order;
	private Set<Order> 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<Order> getOrderList() {
		return orderList;
	}

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

	public Set<Order> getOrderSet() {
		return orderSet;
	}

	public void setOrderSet(Set<Order> 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<String> 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 <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason: TODO ADD REASON. <br/>
 * Date: 2014-5-16 下午5:11:20 <br/>
 * 
 * @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<Order> orderList = new ArrayList<Order>();
		Set<Order> orderSet = new HashSet<Order>();
		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);
	}
}

测试结果:
<?xml version='1.0' encoding='UTF-8'?>
<user>
	<id>1</id>
	<name></name>
	<orderList>
		<order>
			<id>1</id>
			<orderName></orderName>
		</order>
		<order>
			<id>2</id>
			<orderName></orderName>
		</order>
	</orderList>
	<order>
		<id>1</id>
		<orderName></orderName>
	</order>
	<orderSet>
		<order>
			<id>1</id>
			<orderName></orderName>
		</order>
		<order>
			<id>2</id>
			<orderName></orderName>
		</order>
	</orderSet>
</user>
null值属性的节点能够被输出。

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

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值