XStream 使用 NamedMapConverter 序列化自定义地图
XStream serialize custom Map with NamedMapConverter
我正在成功序列化包含 HashMap<String, String>
和 NamedMapConverter
的 Base
class。我的要求已更改,我需要将 HashMap
更改为扩展 HashMap<String, String>
的自定义 StringDictionary
class。
但是在使用 StringDictionary
之后,我的序列化被破坏了。有没有一种方法可以配置 XStream
and/or NamedMapConverter
以保留所需的 xml
输出而无需编写自定义转换器?
在 Android 上使用 XStream 1.4.7。
需要xml
输出:
<base>
<values>
<val key="123">111</val>
<val key="abc">aaa</val>
</values>
</base>
Base
class 使用 HashMap
和 XStream
配置产生以上输出
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);
使用修改后的Base
class
public class Base
{
public Map<String, String> values = new StringDictionary();
}
产生以下不正确的 xml
输出:
<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>
看来没有上面的自定义转换器是无法实现的。但是,在这种情况下,只需对现有转换器稍作调整即可提供自定义转换器。问题在于 NamedMapConverter.canConvert
方法必须被覆盖以包含自定义 StringDictionary
class。
以下代码将为修改后的 Base
class:
生成所需的 xml
输出
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);
另一个更简单(但不完全兼容)的解决方案是将 StringDictionary
class 传递给 NamedMapConverter
构造函数。但是,此解决方案会稍微改变 xml
输出。
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>
我正在成功序列化包含 HashMap<String, String>
和 NamedMapConverter
的 Base
class。我的要求已更改,我需要将 HashMap
更改为扩展 HashMap<String, String>
的自定义 StringDictionary
class。
但是在使用 StringDictionary
之后,我的序列化被破坏了。有没有一种方法可以配置 XStream
and/or NamedMapConverter
以保留所需的 xml
输出而无需编写自定义转换器?
在 Android 上使用 XStream 1.4.7。
需要xml
输出:
<base>
<values>
<val key="123">111</val>
<val key="abc">aaa</val>
</values>
</base>
Base
class 使用 HashMap
和 XStream
配置产生以上输出
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);
使用修改后的Base
class
public class Base
{
public Map<String, String> values = new StringDictionary();
}
产生以下不正确的 xml
输出:
<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>
看来没有上面的自定义转换器是无法实现的。但是,在这种情况下,只需对现有转换器稍作调整即可提供自定义转换器。问题在于 NamedMapConverter.canConvert
方法必须被覆盖以包含自定义 StringDictionary
class。
以下代码将为修改后的 Base
class:
xml
输出
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);
另一个更简单(但不完全兼容)的解决方案是将 StringDictionary
class 传递给 NamedMapConverter
构造函数。但是,此解决方案会稍微改变 xml
输出。
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>