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 {}
我遇到了一个问题,其中 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 {}