5

我正在使用 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,其余字段应被忽略。

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

4

2 回答 2

2

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

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的实现,但我认为它有点复杂。

于 2012-11-26T21:02:25.613 回答
0

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

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

查看 w3schools 上的教程

于 2012-11-27T08:19:15.317 回答