XStream单例模式下反序列化Object-Mapping问题
本文出处:http://blog.csdn.net/chaijunkun/article/details/30257015,转载请注明。由于本人不定期会整理相关博文,会对相应内容作出完善。因此强烈建议在原始出处查看此文。
Java作为面向对象的语言,处理结构化的数据当然也可以将其对象化,这就是涉及到了转化工具。而对于XML文件来说,经常使用的是JDK 1.6开始支持的JAXB 2.0,另外还有一款叫做XStream的框架。本人在使用XStream遇到了一些问题,在此分享。
1.问题描述
2.基础代码
public class TestCase { private static volatile XStream stream= null; public static XStream getStream(){ synchronized (TestCase.class) { if (stream==null){ stream= new XStream(); } return stream; } } public static <T> void toXML(Object obj, Class<T> clazz, OutputStream out){ XStream stream= TestCase.getStream(); stream.processAnnotations(clazz); stream.toXML(obj, out); return; } public static <T> T fromXML(InputStream in, Class<T> clazz){ XStream stream= TestCase.getStream(); stream.processAnnotations(clazz); Object obj= stream.fromXML(in); try{ return clazz.cast(obj); }catch(ClassCastException e){ return null; } } }
<root date="2014-06-12 09:28:34.614 UTC"> <demo> <element>test1</element> </demo> <demo> <element>test2</element> </demo> </root>
结构2:
<root date="2014-06-12 09:28:34.745 UTC"> <example> <element>test1</element> </example> <example> <element>test2</element> </example> </root>
package net.csdn.blog.chaijunkun.xml.case1; import java.util.Date; import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamImplicit; @XStreamAlias("root") public class Case1 { @XStreamAlias("date") @XStreamAsAttribute private Date date; @XStreamImplicit private List<Demo> demos; public Date getDate() { return date; } //一些getters and setters... }
package net.csdn.blog.chaijunkun.xml.case1; import com.thoughtworks.xstream.annotations.XStreamAlias; @XStreamAlias("demo") public class Demo { @XStreamAlias("element") private String element; //一些getters and setters... }
结构2:
package net.csdn.blog.chaijunkun.xml.case2; import java.util.Date; import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamImplicit; @XStreamAlias("root") public class Case2 { @XStreamAlias("date") @XStreamAsAttribute private Date date; @XStreamImplicit private List<Example> examples; //一些getters and setters... }
package net.csdn.blog.chaijunkun.xml.case2; import com.thoughtworks.xstream.annotations.XStreamAlias; @XStreamAlias("example") public class Example { @XStreamAlias("element") private String element; //一些getters and setters... }
3.测试用例
public static void demo1() throws FileNotFoundException{ Demo d1= new Demo(); d1.setElement("test1"); Demo d2= new Demo(); d2.setElement("test2"); List<Demo> demos= new LinkedList<Demo>(); demos.add(d1); demos.add(d2); Case1 c1= new Case1(); c1.setDemos(demos); c1.setDate(new Date()); FileOutputStream out1= new FileOutputStream(new File("d:\\test1.xml")); try{ TestCase.toXML(c1, Case1.class, out1); }finally{ try { out1.close(); } catch (IOException e) { e.printStackTrace(); } } }
结构2的序列化:
public static void demo2() throws FileNotFoundException{ Example e1= new Example(); e1.setElement("test1"); Example e2= new Example(); e2.setElement("test2"); List<Example> examples= new LinkedList<Example>(); examples.add(e1); examples.add(e2); Case2 c2= new Case2(); c2.setExamples(examples); c2.setDate(new Date()); FileOutputStream out2= new FileOutputStream(new File("d:\\test2.xml")); try{ TestCase.toXML(c2, Case2.class, out2); }finally{ try { out2.close(); } catch (IOException e) { e.printStackTrace(); } } }
分别将两个结果保存为test1.xml和test2..xml之后,接下来尝试将它们反序列化过来:
public static void demo3() throws FileNotFoundException{ File f1= new File("d:\\test1.xml"); FileInputStream fis1= new FileInputStream(f1); Case1 c11= TestCase.fromXML(fis1, Case1.class); File f2= new File("d:\\test2.xml"); FileInputStream fis2= new FileInputStream(f2); Case2 c22= TestCase.fromXML(fis2, Case2.class); }
接下来执行JUnit测试用例:
@Test public void doTest() throws FileNotFoundException{ demo1(); demo2(); demo3(); }
发现抛出如下异常:
com.thoughtworks.xstream.converters.ConversionException: Element demo of type net.csdn.blog.chaijunkun.xml.case1.Demo is not defined as field in type net.csdn.blog.chaijunkun.xml.case2.Case2 ---- Debugging information ---- class : net.csdn.blog.chaijunkun.xml.case2.Case2 required-type : net.csdn.blog.chaijunkun.xml.case2.Case2 converter-type : com.thoughtworks.xstream.converters.reflection.ReflectionConverter path : /root/demo line number : 4 version : null ------------------------------- at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.writeValueToImplicitCollection(AbstractReflectionConverter.java:403) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:334) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234) at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) ...........
在错误信息中,path指示要分析的二级节点是demo,而之前规定的结构2的二级节点是example,事实上test2.xml的二级节点也是example。这说明序列化输出没有问题。问题出在了反序列化上。根据错误信息,XStream只存储了第一次反序列化配置的结构,而第二次调用时并没有更新相关注解配置(即使调用了processAnnotations注解)。
4.解决方法
public static XStream getStream(){ return new XStream(); }
此时,两次反序列化都已正常。
5.写在后面
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。