【问题标题】:How to Marshall and Unmarshall Map using JAXB [duplicate]如何使用 JAXB 编组和解组映射 [重复]
【发布时间】:2015-01-08 09:22:51
【问题描述】:

我正在尝试实现一些代码,以便我可以使用 JAXB 编组和解组一些 xml。

基本上,我有一个格式如下的 xml:

<root attribute1="blabla" attribute2="blablabla">
    <register type="1" description="blabla">
        <field description = "blabla" type = "blabla">
    </register>
    <register type="2" description="blabla">
        <field description = "blabla" type = "blabla">
    </register>
</root>

我想创建一个 HashMap if Registers,它的键是寄存器类型,它的值是寄存器本身。

我不知道该怎么做。可能吗?我已经尝试过使用适配器,但是没有用。

有人可以帮我吗?

【问题讨论】:

    标签: java map jaxb


    【解决方案1】:

    使用Map 上的XmlAdapter(将Map 转换为具有ListRegister 对象的域对象),您将能够生成/使用看起来像以下(注意添加了registers 元素):

    <root attribute1="blabla" attribute2="blablabla">
      <registers>
        <register type="1" description="blabla">
            <field description = "blabla" type = "blabla">
        </register>
        <register type="2" description="blabla">
            <field description = "blabla" type = "blabla">
        </register>
      </registers>
    </root>
    

    如果您使用 EclipseLink MOXy 作为您的 JAXB 提供程序,那么您可以使用我们的 @XmlPath 扩展来摆脱那个额外的元素。

    @XmlJavaTypeAdapter(MapAdapter.class)  // Standard JAXB annotation
    @XmlPath(".") // MOXy extension
    private Map<String, Register> registers;
    

    更新

    很遗憾,我无法在此项目中使用 MOXy,也无法更改 xml。有没有什么方法可以在没有 registers 标签的情况下解析它?

    这不是最漂亮的解决方案,但您可以执行以下操作(注意:使用此解决方案,同时编组 Root 的同一实例是不安全的):

    import java.util.*;
    import javax.xml.bind.annotation.*;
    
    @XmlRootElement
    public class Root {
    
        private Map<String, Register> registers = new HashMap<String, Register>();
    
        @XmlElement(name="register")
        private Collection<Register> registerCollection;
    
        @XmlTransient
        public Map<String, Register> getRegisters() {
            return registers;
        }
    
        public void setRegisters(Map<String, Register> registers) {
            this.registers = registers;
        }
    
        private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
            for (Register register : registerCollection) {
                regusters.put(register.getType());
            }
        }
    
        private void beforeMarshal(Marshaller marshaller) {
            if(null != registers) {
                registerCollection = registers.values();
            }
        }
    
    }
    

    【讨论】:

    • 感谢您的回答,布莱斯。不幸的是,我不能在这个项目中使用 MOXy,也不能更改 xml。有没有办法在没有寄存器标签的情况下解析它?再次感谢!
    • @user3302039 - 我已经更新了我的答案以包含一个潜在的解决方法。
    • 我正在尝试明天实施,所以我可以提供反馈。但无论如何,提前谢谢!
    • 布莱斯,很抱歉回复晚了。我的团队决定将实现更改为 List 而不是 Map,因为您所说的不安全。但无论如何,我感谢您的关注和帮助。最好的问候!
    猜你喜欢
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 2012-03-05
    • 2014-05-04
    • 2011-11-24
    • 2012-12-21
    • 2011-03-27
    • 2016-01-26
    相关资源
    最近更新 更多