【问题标题】:Marshalling selected fields only, using JAXB仅编组选定的字段,使用 JAXB
【发布时间】:2012-11-26 19:14:31
【问题描述】:

我正在使用 JAXB 将 java 对象编组为 XML。我面临的问题是并非java对象实例的所有成员变量都需要编组XML。例如,我的完整 XML 文档应该看起来像-

<Disk>
  <status>attached</status>
  <size>10000000000</size>
  <freeSpace>25600000<freeSpace>
  <id>MI45563PO</id>
</Disk>

但在更新的情况下,只有选定的属性会更改,并且只有更改的属性才应该是编组 XML 的一部分。就像“状态”属性可以更改为“分离”一样,在这种情况下,编组的 XML 应该如下所示-

<Disk>
  <status>detached</status>
</Disk>

或者,在“freeSpace”的情况下,XML 应该看起来像-

<Disk>
  <freeSpace>20000000<freeSpace>
</Disk>

我的问题: 将未更改的字段定义为 null(因此将所有原始类型定义为包装类变量,如 Integer、Boolean 等)是获得所需结果的唯一解决方案吗?或者,在 JAXB 中是否有任何方法可以指定选定的字段,这些字段应编组为结果 XML,其余字段应被忽略。

请注意,需要忽略和需要包含的字段集在任何时候都不是固定的。

【问题讨论】:

    标签: java xml jaxb marshalling


    【解决方案1】:

    如果您想拥有一个类的几个视图,您应该为每个视图创建decorator 类。 示例源代码:

    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.annotation.XmlRootElement;
    
    public class Program {
    
        public static void main(String[] args) throws Exception {
            JAXBContext context = JAXBContext.newInstance(Disk.class,
                    OnlyDiskStatusDecorator.class, OnlyDiskFreeSpaceDecorator.class);
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    
            Disk disk = new Disk();
            disk.setStatus("attached");
            disk.setSize(10000000000L);
            disk.setFreeSpace(25600000L);
            disk.setId("MI45563PO");
    
            m.marshal(disk, System.out);
            m.marshal(new OnlyDiskStatusDecorator(disk), System.out);
            m.marshal(new OnlyDiskFreeSpaceDecorator(disk), System.out);
        }
    
    }
    
    @XmlRootElement
    class Disk {
        private String status;
        private long size;
        private long freeSpace;
        private String id;
    
        public String getStatus() {
            return status;
        }
    
        public void setStatus(String status) {
            this.status = status;
        }
    
        public long getSize() {
            return size;
        }
    
        public void setSize(long size) {
            this.size = size;
        }
    
        public long getFreeSpace() {
            return freeSpace;
        }
    
        public void setFreeSpace(long freeSpace) {
            this.freeSpace = freeSpace;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        @Override
        public String toString() {
            return "Disk [status=" + status + ", size=" + size + ", freeSpace="
                    + freeSpace + ", id=" + id + "]";
        }
    }
    
    @XmlRootElement(name = "Disk")
    class OnlyDiskStatusDecorator {
        private Disk disk;
    
        public OnlyDiskStatusDecorator() {
        }
    
        public OnlyDiskStatusDecorator(Disk disk) {
            this.disk = disk;
        }
    
        public String getStatus() {
            return disk.getStatus();
        }
    
        public void setStatus(String status) {
        }
    }
    
    @XmlRootElement(name = "Disk")
    class OnlyDiskFreeSpaceDecorator {
        private Disk disk;
    
        public OnlyDiskFreeSpaceDecorator() {
        }
    
        public OnlyDiskFreeSpaceDecorator(Disk disk) {
            this.disk = disk;
        }
    
        public long getFreeSpace() {
            return disk.getFreeSpace();
        }
    
        public void setFreeSpace(long freeSpace) {
        }
    }
    

    以上示例打印:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <disk>
        <freeSpace>25600000</freeSpace>
        <id>MI45563PO</id>
        <size>10000000000</size>
        <status>attached</status>
    </disk>
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Disk>
        <status>attached</status>
    </Disk>
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Disk>
        <freeSpace>25600000</freeSpace>
    </Disk>
    

    我为两个类视图创建了两个装饰器。第一个用于更新状态的装饰器,第二个用于更新 freeSpace 值的装饰器。您也可以为特定的序列化创建XmlAdapter 的实现,但我认为它有点复杂。

    【讨论】:

    • 我认为当需要编组的字段集已知时,这可能是一种解决方案。当字段的数量很大(10-15 甚至更多)时,为所有可能的组合创建一个装饰器类是不切实际的。感谢您放下代码。
    【解决方案2】:

    您是否考虑过在您的 XML 上使用 XSL Transformation 然后使用 JAXB?

    我也遇到过类似的情况,我有大约 3000 个 JAXB DTO!我将这些减少到一个可管理的数字,28 个。

    查看 w3schools 的 tutorial

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-25
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 2011-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多