XStream笔记

最近在工作中使用Xstream解析xml参考网上文章进行整理归纳如下

1.简介
XStream是一个Java对象和XML相互转换的工具(也支持json的转换),提供了所有的基础类型、数组、集合等类型直接转换的支持.XStream对象相当Java对象和XML之间的转换器,转换过程是双向.使用XStream 不用任何映射就能实现多数 Java 对象的序列化。在生成的 XML 中对象名变成了元素名,类中的字符串组成了 XML 中的元素内容。使用 XStream 序列化的类不需要实现 Serializable 接口。XStream 是一种序列化工具而不是数据绑定工具,就是说不能从 XML 或者 XML Schema Definition (XSD) 文件生成类。 
和其他序列化工具相比,XStream 有三个突出的特点: XStream 不关心序列化/逆序列化的类的字段的可见性。 序列化/逆序列化类的字段不需要 getter 和 setter 方法。 序列化/逆序列化的类不需要有默认构造函数。 不需要修改类,使用 XStream 就能直接序列化/逆序列化任何第三方类 


2.基本使用
Xstream序列化XML时需要引用的jar包:xstream-[version].jar、xpp3-[version].jar、xmlpull-[version].jar。Xstream序列化Json需要引用的jar包:jettison-[version].jar。
使用Xstream序列化时,对JavaBean没有任何限制。JavaBean的字段可以是私有的,也可以没有getter或setter方法,还可以没有默认的构造函数。
2.1 初始化
Xstream序列化XML时可以允许用户使用不同的XML解析器,用户可以使用一个标准的JAXP DOM解析器或自Java6集成StAX解析器。这样用户就不需要依赖xpp3-[version].jar。
XStream xstream = new XStream();//需要XPP3库
XStream xstream = new XStream(new StaxDriver());//不需要XPP3库开始使用Java6
XStream xstream = new XStream(new DomDriver());//不需要XPP3库


2.2 Xstream序列化XML

xstream.toXML(bean); //XML序列化
xstream.fromXML(xml); //XML反序列化


2.3 Xstream序列化JSON

Json解析器:
    JettisonMappedXmlDriver:是支持序列化和反序列化Json的。
    JsonHierarchicalStreamDriver:只支持序列化,不支持反序列化

XStream xstream = new XStream(new JettisonMappedXmlDriver());//设置Json解析器
xstream.setMode(XStream.NO_REFERENCES);//设置reference模型,不引用
xstream.toXML(bean);//Json序列化
xstream.fromXML(xml);//Json反序列化


2.3.1 去掉序列化Json的根节点
Person bean=new Person("张三",19);
XStream xstream = new XStream(new JsonHierarchicalStreamDriver()
{
    public HierarchicalStreamWriter createWriter(Writer writer)
    {
        return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
    }
});
//Json序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
去掉根节点后的Json串是不能反序列化的,因为XStream 不知道它的类型。

2.4 Xstream序列化重命名

Xstream.aliasPackage() 为包重命名
    xstream.aliasPackage("com.lzw", "test");//为包名称重命名
Xstream.alias() //为类重命名
    xstream.alias("人", Person.class);//为类名节点重命名
Xstream.aliasField() 为字段重命名
    xstream.aliasField("姓名", Person.class,"name");//为类的字段节点重命名
Xstream.addImplicitCollection() 省略集合根节点
    xstream.addImplicitCollection(Person.class, "friends");//省略集合根节点
Xstream.useAttributeFor() 把字段节点设置成属性
    xstream.useAttributeFor(Person.class, "name");//把字段节点设置成属性
Xstream.omitField() 隐藏字段
    xstream.omitField(Person.class, "friends");//把字段节点隐藏
Xstream.registerConverter() 注册转换器 
    xstream.registerConverter(new AuthorConverter());  


3.Xstream注解

使用Xstream注解前需要对Xstream进行配置,可以使用两种方式:应用某个JavaBean类的注解或自动使用JavaBean类的注解;自动侦查注解与XStream.processAnnotations(Class[] cls)的区别在于性能.自动侦查注解将缓存所有类的类型
    XStream xstream = new XStream();
    xstream.processAnnotations(Person.class);//应用Person类的注解
    xstream.autodetectAnnotations(true);//自动检测注解

3.1 注解详解

@XStreamAlias() 重命名
    @XStreamAlias("人")
    class Person
@XStreamImplicit 省略集合根节点
    //@XStreamImplicit//只隐藏集合根节点
    @XStreamImplicit(itemFieldName="朋友")//设置重复的节点名,可能会导致无法反序列化
@XStreamAsAttribute 把字段节点设置成属性
    @XStreamAsAttribute
    private String name;
@XStreamOmitField 隐藏字段
    @XStreamOmitField
    private List<String> friends;
@XStreamConverter() 设置转换器
    @XStreamConverter(value=BooleanConverter.class,booleans={false},strings={"男","女"})
    private boolean sex;

3.2 转换器converter

3.2.1 Xstream自带的转换器
    Xstream内部有许多转换器,用于JavaBean对象到XML或Json之间的转换。这些转换器的详细信息网址:http://xstream.codehaus.org/converters.html

3.2.2 自定义的转换器
    
public class PersonConverter implements Converter 
{
    @Override//定义转换器能转换的JavaBean类型
    public boolean canConvert(Class type)
    {
        return type.equals(Person.class);
    }
    @Override//把对象序列化成XML或Json
    public void marshal(Object value, HierarchicalStreamWriter writer, 
MarshallingContext context)
    {
        Person person = (Person) value;
        writer.startNode("姓名");
        writer.setValue(person.getName());
        writer.endNode();
        writer.startNode("年龄");
        writer.setValue(person.getAge()+"");
        writer.endNode();
        writer.startNode("转换器");
        writer.setValue("自定义的转换器");
        writer.endNode();
    }
    @Override//把XML或Json反序列化成对象
    public Object unmarshal(HierarchicalStreamReader reader, 
UnmarshallingContext context)
    {
           Person person = new Person("",-1);
           reader.moveDown();
           person.setName(reader.getValue());
           reader.moveUp();
           reader.moveDown();
           person.setAge(Integer.parseInt(reader.getValue()));
           reader.moveUp();
           return person;
    }
}

XStream xstream = new XStream();
xstream.registerConverter(new PersonConverter());//注册转换器


诸如: xstream处理null值属性转换 等问题都需要自定义转换器

xstream处理null值属性转换:
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;  
    }  
  
}  

3.2.3 常用的转换器接口与抽象类
      SingleValueConverter:单值转换接口
    AbstractSingleValueConverter:单值转换抽象类
    Converter:常规转换器接口


4.Xstream对象流

XStream对象流是通过标准java.io.ObjectOutputStream和java.io.ObjectInputStream对象。因为XML文档只能有一个根节点,必须包装在一个序列化的所有元素 额外的根节点。 这个根节点默认 < object-stream > 的使用

Xstream对象输出流
XStream xstream = new XStream();
ObjectOutputStream out = xstream.createObjectOutputStream(System.out);
out.writeObject(new Person("张三",12));
out.writeObject(new Person("李四",19));
out.writeObject("Hello");
out.writeInt(12345);
out.close();


Xstream对象输出流
StringReader reader = new StringReader(s);
XStream xstream = new XStream();
ObjectInputStream in = xstream.createObjectInputStream(reader);
System.out.println((Person) in.readObject());
System.out.println(in.readInt());

5.Xstream持久化

5.1 保存JavaBean对象
PersistenceStrategy strategy = new FilePersistenceStrategy(new File("D:\\tmp"));
List list = new XmlArrayList(strategy);
list.add(new Person("张三",13));//保存数据
list.add(new Person("李四",21));
list.add(new Person("王五",17));
检查D:\tmp目录,有三个文件:int@0.xml、int@1.xml、int@2.xml;每个对象都被序列化到XML文件里

5.2 读取并删除JavaBean对象

PersistenceStrategy strategy = new FilePersistenceStrategy(new File("D:\\tmp"));
List list = new XmlArrayList(strategy);
for (Iterator it = list.iterator(); it.hasNext();)
{
    System.out.println((Person) it.next());
    it.remove();//删除对象序列化文件
}
 

转载于:https://my.oschina.net/u/3275937/blog/1553925

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值