XStream serialization library声称在开箱即用的序列化复杂Java对象方面是健壮的(例如,不需要修改对象或映射)。特别是,根据XStream docs,XStream可以处理循环对象引用。
所以我写了一个测试来检查这个 - 我试图序列化一个有点复杂的数据结构(LinkedHashMultimap
),其中包含对iteself的引用:
import com.google.common.collect.LinkedHashMultimap;
import com.thoughtworks.xstream.XStream;
public class SerializationTest {
public static void main(String[] args0) {
// Create LinkedHashMultimap to serialize
LinkedHashMultimap<String, Object> outObj = LinkedHashMultimap.create();
outObj.put("x", 1);
outObj.put("x", "abc");
outObj.put("y", outObj); // Add a self-reference
// Try to serialize
XStream xstream = new XStream();
String xml = xstream.toXML(outObj);
System.out.println(xml); // Print XML to console for a quick peek
// Try to deserialize - ERROR HERE!!!
LinkedHashMultimap<String, Object> inObj = (LinkedHashMultimap<String, Object>)xstream.fromXML(xml);
System.out.println(inObj);
}
}
序列化的XML对象如下所示:
<com.google.common.collect.LinkedHashMultimap serialization="custom">
<unserializable-parents/>
<com.google.common.collect.LinkedHashMultimap>
<default/>
<int>2</int>
<int>2</int>
<string>x</string>
<string>y</string>
<int>3</int>
<string>x</string>
<int>1</int>
<string>x</string>
<string>abc</string>
<string>y</string>
<com.google.common.collect.LinkedHashMultimap reference="../.."/>
</com.google.common.collect.LinkedHashMultimap>
</com.google.common.collect.LinkedHashMultimap>
但是,反序列化(即对xstream.fromXML()
的调用)失败并显示NullPointerException
例外:
Exception in thread "main" com.thoughtworks.xstream.converters.ConversionException: Could not call com.google.common.collect.LinkedHashMultimap.readObject() : null
---- Debugging information ----
message : Could not call com.google.common.collect.LinkedHashMultimap.readObject()
cause-exception : java.lang.NullPointerException
cause-message : null
class : com.google.common.collect.LinkedHashMultimap
required-type : com.google.common.collect.LinkedHashMultimap
converter-type : com.thoughtworks.xstream.converters.reflection.SerializableConverter
path : /com.google.common.collect.LinkedHashMultimap/com.google.common.collect.LinkedHashMultimap
line number : 15
version : 1.4.7
-------------------------------
at com.thoughtworks.xstream.converters.reflection.SerializationMethodInvoker.callReadObject(SerializationMethodInvoker.java:119)
at com.thoughtworks.xstream.converters.reflection.SerializableConverter.doUnmarshal(SerializableConverter.java:454)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:257)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50)
Disconnected from the target VM, address: '127.0.0.1:50107', transport: 'socket'
at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134)
at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1185)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1169)
at com.thoughtworks.xstream.XStream.fromXML(XStream.java:1040)
at com.thoughtworks.xstream.XStream.fromXML(XStream.java:1031)
at SerializationTest3.main(SerializationTest3.java:18)
Caused by: java.lang.NullPointerException
at com.google.common.collect.AbstractMapBasedMultimap$AsMap.hashCode(AbstractMapBasedMultimap.java:1289)
at com.google.common.collect.AbstractMultimap.hashCode(AbstractMultimap.java:228)
at com.google.common.collect.LinkedHashMultimap.hashCode(LinkedHashMultimap.java:81)
at com.google.common.collect.Hashing.smearedHash(Hashing.java:51)
at com.google.common.collect.LinkedHashMultimap$ValueSet.add(LinkedHashMultimap.java:416)
at com.google.common.collect.LinkedHashMultimap.readObject(LinkedHashMultimap.java:574)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.thoughtworks.xstream.converters.reflection.SerializationMethodInvoker.callReadObject(SerializationMethodInvoker.java:113)
... 13 more
所以有人知道为什么会这样吗?以及如何解决这个问题?
答案 0 :(得分:1)
使用:
XStream xstream = new XStream();
xstream.setMode(XStream.XPATH_RELATIVE_REFERENCES);