问题
I am successfully serializing my Base
class containing HashMap<String, String>
with NamedMapConverter
. My requirements have changed and I need to change HashMap
to custom StringDictionary
class that extends HashMap<String, String>
.
But after using StringDictionary
, my serialization got broken. Is there a way to configure XStream
and/or NamedMapConverter
to preserve needed xml
output without writing custom converters?
Using XStream 1.4.7 on Android.
Required xml
output:
<base>
<values>
<val key="123">111</val>
<val key="abc">aaa</val>
</values>
</base>
Base
class with HashMap
and XStream
configuration that produces above output
public class Base
{
public Map<String, String> values = new HashMap<>();
}
Base base = new Base();
base.values.put("abc", "aaa");
base.values.put("123", "111");
XStream xs = new XStream();
xs.alias("base", Base.class);
NamedMapConverter c = new NamedMapConverter(xs.getMapper(), "val", "key", String.class, null, String.class, true, false, xs.getConverterLookup());
xs.registerConverter(c);
String s = xs.toXML(base);
Using modified Base
class
public class Base
{
public Map<String, String> values = new StringDictionary();
}
produces following incorrect xml
output:
<base>
<values class="com.test.StringDictionary" serialization="custom">
<unserializable-parents/>
<map>
<default>
<loadFactor>0.75</loadFactor>
</default>
<int>4</int>
<int>2</int>
<string>123</string>
<string>111</string>
<string>abc</string>
<string>aaa</string>
</map>
</values>
</base>
回答1:
It seems that without custom converter above is impossible to achieve. However, in this case custom converter can be provided with only slight tweaking of existing one. Problem lies in NamedMapConverter.canConvert
method that has to be overridden to include custom StringDictionary
class.
Following code will produce required xml
output for modified Base
class:
XStream xs = new XStream();
xs.alias("base", Base.class);
xs.addDefaultImplementation(StringDictionary.class, Map.class);
NamedMapConverter c = new NamedMapConverter(xs.getMapper(), "val", "key", String.class, null, String.class, true, false, xs.getConverterLookup())
{
public boolean canConvert(Class type)
{
if (type.equals(StringDictionary.class)) return true;
else return super.canConvert(type);
}
};
xs.registerConverter(c);
Another simpler (but not fully compliant) solution, is to pass StringDictionary
class to NamedMapConverter
constructor. However this solution will slightly change xml
output.
XStream xs = new XStream();
xs.alias("base", Base.class);
NamedMapConverter c = new NamedMapConverter(StringDictionary.class, xs.getMapper(), "val", "key", String.class, null, String.class, true, false, xs.getConverterLookup());
xs.registerConverter(c);
<base>
<values class="com.test.StringDictionary">
<val key="123">111</val>
<val key="abc">aaa</val>
</values>
</base>
来源:https://stackoverflow.com/questions/32296215/xstream-serialize-custom-map-with-namedmapconverter