日常使用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;
}
}
/**
* 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值属性的节点能够被输出。
仓促写成,应该还有很多问题,如果有疑问请留言交流。