有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JAXB使用XML适配器读入地图

我正在努力实现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映射有(键1,值1),(键2,值2)和outputData映射有(键3,值3)

这是我写的

@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函数,它是零,这意味着我无法正确读取标记的信息。任何帮助都将不胜感激


共 (1) 个答案

  1. # 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;
    }
    

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

    我用下面的测试代码实现了这一点

    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输出包含<item .../>个元素 而不是想要的<Param .../>元素。 由此你也可以得出结论:你的解组代码没有处理 <Param ... />个元素,因为它需要<item ... />个元素

    所以你有两个选择:

    • 将XML输入更改为使用<item>而不是<Param>
    • 告诉JAXB,您的MapElement类对应于<Param>XML元素。 我把这件事的细节留给你来解决