【问题标题】:Convert Map to inline element, text XML将 Map 转换为内联元素,文本 XML
【发布时间】:2015-02-19 13:01:22
【问题描述】:

考虑以下 Map 结构(为简化为 JSON):

{
    "key1": "value1",
    "key2": "value2"
}

使用Java的SimpleXML框架,考虑到地图是Parent的类变量,我如何转换为以下XML。

<Parent>
  <key1>value1</key1>
  <key2>value2</key2>
</Parent>

我查看了有关内联映射等的 SimpleXML 教程,但它缺乏解决方案。我想我需要实现某种自定义序列化程序。 ?

【问题讨论】:

    标签: java android xml xml-serialization simple-framework


    【解决方案1】:

    据我所知,正确的结构应该是:

    <Parent>
      <mapFieldOfTheParentClass>
        <key1>value1</key1>
        <key2>value2</key2>
      </mapFieldOfTheParentClass>
    </Parent>
    

    这是因为您的类可能有一个名为“key1”的字段,并且无法将其与地图的键区分开来。但是,如果您确定要使用自己的结构,只要不发生冲突,自定义序列化程序就可以工作。

    【讨论】:

    • 我大体上同意,但我与之通信的服务器需要我概述的格式。消息是明确指定的,因此冲突/重复键是我的实现的错误结果。谢谢。
    【解决方案2】:

    我需要实现某种自定义序列化程序。

    在这种情况下,您将无法解决这个问题。不过好在并不复杂。

    这是一个例子:

    @Root(name = "Parent")
    @Convert(Example.ParentConverter.class)
    public class Example
    {
        private Map<String, String> values;
    
        // ...
    
        static class ParentConverter implements Converter<Example>
        {
    
            @Override
            public Example read(InputNode node) throws Exception
            {
                Example value = new Example();
                value.values = new HashMap<>();
                InputNode next;
    
                while( ( next = node.getNext() ) != null )
                {
                   value.values.put(next.getName(), next.getValue());
                }
    
                return value;
            }
    
            @Override
            public void write(OutputNode node, Example value) throws Exception
            {
                // Implement to support writing too
                throw new UnsupportedOperationException("Not supported yet.");
            }
        }
    }
    

    @Convert 需要例如。 AnnotationStrategy:

    Serializer ser = new Persister(new AnnotationStrategy());
    Example e = ser.read(Example.class, xml); // xml = input xml
    

    编辑:

    仅地图字段转换器的可能实现:

    @Override
    public void write(OutputNode node, Map<String, String> value) throws Exception
    {
        final OutputNode parent = node.getParent();
    
        if( !value.isEmpty() )
        {
            boolean first = true;
    
            for( Map.Entry<String, String> e : value.entrySet() )
            {
                if( first == true )
                {
                    node.setName(e.getKey());
                    node.setValue(e.getValue());
                    // Remove generated 'class' attribute for collections
                    node.getAttributes().remove("class");
                    first = false;
                }
                else
                {
                    parent.getChild(e.getKey()).setValue(e.getValue());
                }
            }
        }
        else
        {
            // Handle empty maps
        }
    }
    

    【讨论】:

    • 谢谢。可以仅将转换应用于示例的值成员,而不是整个类。我宁愿只处理那个领域。另外,我问的是序列化,但我可以弄清楚另一面。谢谢。
    • 你可以这样做,只需为该字段的类型实现一个转换器,添加@Convert(...) @Element 注释。但这对于阅读来说可能会很棘手。但是,如果您只想 write (对不起,误读了您的问题),它会起作用。提示:转换器将为地图创建一个包装器元素。要解决此问题,只需将其修改为第一个值并删除 class 属性。如果遇到麻烦,请在此处报告。
    • 我添加了一个如何实现转换器的示例(只写)。
    猜你喜欢
    • 2013-04-06
    • 2020-06-30
    • 2015-04-28
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多