2
我想要用xStream序列化BiMap。由於我不喜歡由BiStream自動生成的xStream代碼,我認爲將BiMap轉換爲HashMap並序列化HashMap或反序列化時可能是一個好主意,我只需再次讀入HashMap並將其轉換回來到BiMap。所以我想出了以下轉換器策略:使用xStream序列化BiMap
public class XStreamBiMapConverterExample
{
public void run()
{
XStream xStream = new XStream();
xStream.setMode(XStream.XPATH_ABSOLUTE_REFERENCES);
xStream.registerConverter(new BiMapConverter(), XStream.PRIORITY_VERY_HIGH);
final String xml = xStream.toXML(new ObjectToSerialize());
System.out.println(xml);
xStream.fromXML(xml);//Reading does not work, if the BiMap of ObjectToSerialize is empty
}
public static void main(final String[] args)
{
new XStreamBiMapConverterExample().run();
}
}
class ObjectToSerialize
{
// Map<String, Integer> serializeMap = new HashMap<>();
BiMap<String, Integer> serializeMap = HashBiMap.create();
public ObjectToSerialize()
{
//If there is no Values, my Converter fails. With Value there is no Problem.
// serializeMap.put("Hallo", 7);
}
}
class BiMapConverter implements Converter
{
@Override
public boolean canConvert(@SuppressWarnings("rawtypes") final Class type)
{
return BiMap.class.isAssignableFrom(type);
}
@Override
public void marshal(final Object source, final HierarchicalStreamWriter writer,
final MarshallingContext context)
{
final BiMap<?, ?> biMap = (BiMap<?, ?>) source;
final HashMap<?, ?> convertBiMapToHashMap = convertMapToHashMap(biMap);
context.convertAnother(convertBiMapToHashMap);
}
private <K, V> HashMap<K, V> convertMapToHashMap(final Map<K, V> map)
{
final HashMap<K, V> hashMap = new HashMap<>();
for (Entry<K, V> entry : map.entrySet())
{
hashMap.put(entry.getKey(), entry.getValue());
}
return hashMap;
}
@Override
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context)
{
final HashMap<?, ?> serializedMap =
(HashMap<?, ?>) context.convertAnother(reader.getValue(), HashMap.class);
return convertMapToBiMap(serializedMap);
}
private <K, V> BiMap<K, V> convertMapToBiMap(final Map<K, V> map)
{
final BiMap<K, V> biMap = HashBiMap.create();
for (Entry<K, V> entry : map.entrySet())
{
biMap.put(entry.getKey(), entry.getValue());
}
return biMap;
}
}
這工作得很好,因爲xStream已經可以轉換HashMaps了。奇怪的是,它只有在BiMap中有值時才起作用。如果BIMAP是空的,我得到下面的異常,在解組數據:
Exception in thread "main" com.thoughtworks.xstream.converters.ConversionException: only START_TAG can have attributes END_TAG seen ...ize>\n <serializeMap class="com.google.common.collect.HashBiMap"/>... @2:62 : only START_TAG can have attributes END_TAG seen ...ize>\n <serializeMap class="com.google.common.collect.HashBiMap"/>... @2:62
---- Debugging information ----
message : only START_TAG can have attributes END_TAG seen ...ize>\n <serializeMap class="com.google.common.collect.HashBiMap"/>... @2:62
cause-exception : java.lang.IndexOutOfBoundsException
cause-message : only START_TAG can have attributes END_TAG seen ...ize>\n <serializeMap class="com.google.common.collect.HashBiMap"/>... @2:62
class : com.google.common.collect.HashBiMap
required-type : com.google.common.collect.HashBiMap
converter-type : BiMapConverter
path : /ObjectToSerialize/serializeMap
line number : 2
class[1] : ObjectToSerialize
converter-type[1] : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
version : 1.4.6
-------------------------------
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:79)
at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
...
使用轉換器(!當BIMAP爲空)後生成的輸出如下:
<ObjectToSerialize>
<serializeMap class="com.google.common.collect.HashBiMap"/>
</ObjectToSerialize>
誰能告訴我,我做錯了什麼?
作品很有魅力,謝謝!猜猜我必須深入挖掘API以瞭解,爲什麼這是行得通的。 – crusam 2014-09-02 07:34:02
謝謝我很好奇你是怎麼想出來的?這個功能沒有javadoc! – Hunsu 2015-04-04 12:18:43
'getValue()'將解析器推進到元素的結束標記。之後,沒有屬性可以被讀取,因此錯誤。非常模糊。 – 2015-04-16 21:21:29