XStream:将没有共享根元素的元素反序列化到Map中?

时间:2014-08-20 19:54:50

标签: xml serialization xstream

我正在尝试将xml元素列表反序列化为Map,其中id属性作为键和字符串,它作为值位于元素内部。遗憾的是,转换元素集合没有共享的根元素,然后可以将其别名化为Map实例。使用Collections有addImplicitCollection方法可以解决这个问题,对于Maps有没有相应的解决方案?

有一段代码可以更准确地解释我想要实现的目标:

import com.thoughtworks.xstream.XStream;
import java.io.FileNotFoundException;
import java.util.Map;
import static org.junit.Assert.*;
import org.junit.Test;

public class XStreamMapDeserializationTest {

public static class Entry {

    private String id;
    Map<String, Translation> translations;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Map<String, Translation> getTranslations() {
        return translations;
    }

    public void setTranslations(Map<String, Translation> translations) {
        this.translations = translations;
    }

}

public static class Translation {

    private String id;
    private String text;

    public String getId() {
        return id;
    }

    public String getText() {
        return text;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setText(String text) {
        this.text = text;
    }
}

@Test
public void testUnmarshall_shouldProperlyUnmarshallSingleEntry() {
    //given
    String xmlToUnmarshall
            = "<entry id=\"0\">\n"
            + "  <translation id=\"0\">\n"
            + "    <text>autumn</text>\n"
            + "  </translation>\n"
            + "  <translation id=\"1\">\n"
            + "    <text>der Herbst</text>\n"
            + "  </translation>\n"
            + "</entry>";

    XStream xstream = new XStream();
    xstream.alias("entry", Entry.class);
    xstream.alias("translation", Translation.class);

    //when
    Entry result = (Entry) xstream.fromXML(xmlToUnmarshall);
    //then
    assertNotNull("Entry should not be equal null", result);
}
}

1 个答案:

答案 0 :(得分:0)

我最终为Entry类实现了转换器,每次它找到转换节点时它反序列化它并添加到map中,并在最后集中创建Map作为Entry字段。

class EntryConverter implements Converter {

    @Override
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        Entry entry = new Entry();
        Map<String, Translation> translations = new HashMap<>();
        while (reader.hasMoreChildren()) {
            reader.moveDown();
            String nodeName = reader.getNodeName();
            if ("translation".equalsIgnoreCase(nodeName)) {
                String id = reader.getAttribute("id");
                Translation translation = (Translation) context.convertAnother(null, Translation.class);

                translations.put(id, translation);
            }
            reader.moveUp();
        }
        entry.setTranslations(translations);
        return entry;
    }

    @Override
    public boolean canConvert(Class type) {
        return Entry.class.isAssignableFrom(type);
    }

}

然后我刚刚将转换器添加到xstream配置中:

xstream.registerConverter(new EntryConverter());