【问题标题】:JAXB Use XML Adapter to Read in MapJAXB 使用 XML 适配器读取 Map
【发布时间】:2021-08-04 03:25:08
【问题描述】:

我正在尝试实现this,其中

<SomeXml>
   <SomeData>...</SomeData>
   <InputData>
       <Param key="key1" value="value1" />
       <Param key="key2" value="value2" />
   </InputData>
   <OutputData>
       <Param key="key3" value="value3" />
   </OutputData>
</SomeXml>

变成

public class SomeXml {
    private SomeData someData;
    private Map<String, String> inputData;
    private Map<String, String> outputData;
}

inputData map 有 (key1, value1), (key2, value2) 而 outputData map 有 (key3, value3)。

这是我写的;

@NoArgsConstructor
@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class MapElement {

    @XmlAttribute(name = "key')
    private String key;

    @XmlAttribute(name = "value")
    private String value;
}

@NoArgsConstructor
public class MapAdapter extends XmlAdapter<MapElement[], Map<String, String>> {

    public MapElement[] marshal(Map<String, String> args) throws Exception {
        MapElement[] mapElements = new mapElement[args.size()];
        int i = 0;
        for (Map.Entry<String, String> entry : args.entrySet()) {
            mapElements[i++] = new MapElement(entry.getKey(), entry.getValue());
        }

        return mapElements;
    }

    public Map<String, String> unmarshal(MapElement[] args) throws Exception {
        Map<String, String> m = new TreeMap<>();
        for (MapElement elem : args) {
            m.put(elem.getKey(), elem.getValue());
        }
        return m;
    }
}    

@NoArgsConstructor
@AllArgsConstructor
@XmlAccessorType(XmlAccessorType.FIELD)
@XmlRootElement
public class SomeXml {

    @XmlElement
    private SomeData someData;

    @XmlJavaAdapter(MapAdapter.class)
    @XmlElement(name = "InputData")
    private Map<String, String> inputData;

    @XmlJavaAdapter(MapAdapter.class)
    @XmlElement(name = "OutputData")
    private Map<String, String> outputData;
}

据我所知,InputData 和 OutputData 映射是非空的,因此正在创建它们,但是在检查 MapAdapter.unmarshal 函数的参数长度时,它为零,这意味着我不是能够正确读取标记的信息。任何帮助将不胜感激。

【问题讨论】:

    标签: java xml parsing jaxb


    【解决方案1】:

    在您发布的代码中,您的 SomeXml 类看起来非常不完整, 因为它缺少所需的 JAXB 注释。 我不知道这些注释是否也丢失了 在您的真实代码中,或者如果您只是忘记将它们写在您的帖子中。 无论如何,注释应该是这样的:

    @Getter
    @Setter
    @XmlRootElement(name = "SomeXml")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class SomeXml {
        @XmlElement(name = "SomeData")
        private SomeData someData;
        
        @XmlElement(name = "InputData")
        @XmlJavaTypeAdapter(MapAdapter.class)
        private Map<String, String> inputData;
    
        @XmlElement(name = "OutputData")
        @XmlJavaTypeAdapter(MapAdapter.class)
        private Map<String, String> outputData;
    }
    

    我的第一个建议是:
    从调试 marshalling 部分开始, 因为这比调试 unmarshalling 部分要容易得多。 通过这样做,您将发现并解决代码中的一些问题 这也会破坏你的解组。

    我用下面的测试代码做到了这一点

    SomeXml someXml = new SomeXml();
    someXml.setSomeData(new SomeData());
    Map<String, String> inputData = new HashMap<>();
    inputData.put("key1", "value1");
    inputData.put("key2", "value2");
    someXml.setInputData(inputData);
    Map<String, String> outputData = new HashMap<>();
    outputData.put("key3", "value3");
    outputData.put("key4", "value4");
    someXml.setOutputData(outputData);
        
    JAXBContext context = JAXBContext.newInstance(SomeXml.class);
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(someXml, System.out);
    

    并得到以下 XML 输出:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <SomeXml>
        <SomeData/>
        <InputData>
            <item key="key1" value="value1"/>
            <item key="key2" value="value2"/>
        </InputData>
        <OutputData>
            <item key="key3" value="value3"/>
            <item key="key4" value="value4"/>
        </OutputData>
    </SomeXml>
    

    在这里你看到你的MapAdapter 类在编组方面做得很好。 但有一个问题。编组的 XML 输出具有 &lt;item .../&gt; 元素 而不是想要的&lt;Param .../&gt; 元素。 由此您还可以得出结论:您的解组代码没有处理 &lt;Param ... /&gt; 元素,因为它需要 &lt;item ... /&gt; 元素。

    所以你有两个选择:

    • 将您的 XML 输入更改为使用 &lt;item&gt; 而不是 &lt;Param&gt;
    • 告诉 JAXB 您的 MapElement 类对应于 &lt;Param&gt; XML 元素。 我把它留给你来解决这个细节。

    【讨论】:

    • 我在这篇文章中写了我的 SomeXml 类两次,一次是为了展示我想要什么,一次是为了展示我是如何实现它的。我没有测试这个结果,因为我们找到了一种不同的方法来解决这个问题,但它看起来很准确,所以谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多