JAXB 元素列表中缺少字段

JAXB missing fields in list of elements

我遇到了一个问题,其中 class 的层次结构可以相互包含并且都扩展了一个基础 class,其中一个在添加到列表时不会显示详细信息'base' 个对象。由于某些原因,我必须使用 JAXB,所以我试图找出丢失或错误的地方。我已将其简化为下面的示例代码。

public class BaseSchema {}

@XmlRootElement(name="ObjectA")
@XmlAccessorType(XmlAccessType.FIELD)
public class ObjectA extends BaseSchema {
  private String thingA;
  @XmlElementWrapper(name="listOfBs")
  @XmlElement(name="b-item")
  private List<ObjectB> listB = new ArrayList<>();
  // getters and setters
}

@XmlAccessorType(XmlAccessType.FIELD)
public class ObjectB extends BaseSchema {
  private String thingB;
  @XmlElementWrapper(name="listOfCs")
  @XmlElement(name="c-item")
  private List<ObjectC> listC = new ArrayList<>();
  // getters and setters
}

@XmlAccessorType(XmlAccessType.FIELD)
public class ObjectC extends BaseSchema {
  private String thingC;
  @XmlElementWrapper(name="listOfBases")
  @XmlElement(name="base-item")
  private List<BaseSchema> listBase = new ArrayList<>();
  // getters and setters
}

@XmlAccessorType(XmlAccessType.FIELD)
public class ObjectD extends BaseSchema {
  private String thingD;
  // getter and setter
}

我的根始终是已知元素类型 (ObjectA),因此它是唯一带有 XmlRootElement 标签的元素。现在对于一个 A 的样本数据集持有一个 B 持有一个 C 持有每个的一些,这是编组输出(首先是 JAXB,然后是 XStream 来显示数据在那儿)。您可以看到 JAXB 只是为 D 项输出一个 'blank' 元素,内部字段为 none - 但其余所有工作正常。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ObjectA>
    <thingA>Base element</thingA>
    <listOfBs>
        <b-item>
            <thingB>B1</thingB>
            <listOfCs>
                <c-item>
                    <thingC>C1</thingC>
                    <listOfBases>
                        <base-item xsi:type="objectA" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <thingA>A1</thingA>
                            <listOfBs/>
                        </base-item>
                        <base-item/>
                        <base-item xsi:type="objectA" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <thingA>A2</thingA>
                            <listOfBs/>
                        </base-item>
                        <base-item xsi:type="objectB" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <thingB>B2</thingB>
                            <listOfCs/>
                        </base-item>
                        <base-item xsi:type="objectC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <thingC>C2</thingC>
                            <listOfBases/>
                        </base-item>
                        <base-item/>
                    </listOfBases>
                </c-item>
            </listOfCs>
        </b-item>
    </listOfBs>
</ObjectA>

===================
<test.schema.ObjectA>
  <thingA>Base element</thingA>
  <listB>
    <test.schema.ObjectB>
      <thingB>B1</thingB>
      <listC>
        <test.schema.ObjectC>
          <thingC>C1</thingC>
          <listBase>
            <test.schema.ObjectA>
              <thingA>A1</thingA>
              <listB/>
            </test.schema.ObjectA>
            <test.schema.ObjectD>
              <thingD>D1</thingD>
            </test.schema.ObjectD>
            <test.schema.ObjectA>
              <thingA>A2</thingA>
              <listB/>
            </test.schema.ObjectA>
            <test.schema.ObjectB>
              <thingB>B2</thingB>
              <listC/>
            </test.schema.ObjectB>
            <test.schema.ObjectC>
              <thingC>C2</thingC>
              <listBase/>
            </test.schema.ObjectC>
            <test.schema.ObjectD>
              <thingD>D2</thingD>
           </test.schema.ObjectD>
          </listBase>
        </test.schema.ObjectC>
      </listC>
    </test.schema.ObjectB>
  </listB>
</test.schema.ObjectA>
===================

创建输出的代码:

public class MarshalTest {
  public void test() throws Exception {
    ObjectA base = new ObjectA();
    base.setThingA("Base element");

    ObjectB b1 = new ObjectB();
    b1.setThingB("B1");
    base.getListB().add(b1);

    ObjectC c1 = new ObjectC();
    c1.setThingC("C1");
    b1.getListC().add(c1);

    ObjectA a1 = new ObjectA();
    a1.setThingA("A1");
    c1.getListBase().add(a1);

    ObjectD d1 = new ObjectD();
    d1.setThingD("D1");
    c1.getListBase().add(d1);

    ObjectA a2 = new ObjectA();
    a2.setThingA("A2");
    c1.getListBase().add(a2);

    ObjectB b2 = new ObjectB();
    b2.setThingB("B2");
    c1.getListBase().add(b2);

    ObjectC c2 = new ObjectC();
    c2.setThingC("C2");
    c1.getListBase().add(c2);

    ObjectD d2 = new ObjectD();
    d2.setThingD("D2");
    c1.getListBase().add(d2);

    JAXBContext jaxbContext = JAXBContext.newInstance(base.getClass());
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    StringWriter writer = new StringWriter();

    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    jaxbMarshaller.marshal(base, writer);
    System.out.println(writer.toString());
  }

我认为问题是 JAXB 不知道您的 ObjectD class。您可以尝试将 @XmlSeeAlso({ ObjectA.class, ObjectB.class, ObjectC.class, ObjectD.class }) 添加到您的 BaseSchema class 中吗? 例如

@XmlSeeAlso({ ObjectA.class, ObjectB.class, ObjectC.class, ObjectD.class }
public class BaseSchema {}