XStream使用NamedMapConverter序列化自定义Map

时间:2015-08-30 11:46:25

标签: java android xstream

我正在使用Base成功序列化包含HashMap<String, String>的{​​{1}}课程。我的要求已更改,我需要将NamedMapConverter更改为扩展HashMap的自定义StringDictionary类。

但在使用HashMap<String, String>后,我的序列化被破坏了。有没有办法配置StringDictionary和/或XStream以保留所需的NamedMapConverter输出,而无需编写自定义转换器?

在Android上使用XStream 1.4.7。

必需xml输出:

xml
带有<base> <values> <val key="123">111</val> <val key="abc">aaa</val> </values> </base> Base配置的

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

产生以下不正确的public class Base { public Map<String, String> values = new StringDictionary(); } 输出:

xml

1 个答案:

答案 0 :(得分:0)

似乎没有上面的自定义转换器是不可能实现的。但是,在这种情况下,可以提供自定义转换器,只对现有转换器进行轻微调整。问题在于NamedMapConverter.canConvert方法,必须重写以包含自定义StringDictionary类。

以下代码将为修改后的xml类生成所需的Base输出:

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类传递给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>