与标题一样,我有两个不同的对象实现相同的界面,我想将它们添加到同一个集合中。
我的XML看起来像:
<root>
<item-list>
<item>
<type1>
<id>1</id>
</type1>
</item>
<item>
<type2>
<id>2</id>
<other>1</other>
</type2>
</item>
</item-list>
</root>
item
下的标记可以随时type1
或type2
。它们具有相似的值,但如您所见,type2
还有另一个字段。
我的界面是:
public interface Item {
public String getID();
}
我的三个班级:
public class MyObj {
private ArrayList<Item> items = new ArrayList<Item>();
public List<Item> getItems() {
return items;
}
}
public class Type1 implements Item{
private String id;
@Override
public String getID() {
return id;
}
}
public class Type2 implements Item {
private String id;
private String other;
@Override
public String getID() {
return id;
}
public String getOther() {
return other;
}
}
我的绑定看起来像这样:
<binding direction="input" >
<mapping name="item-list" class="jibx.woe.MyObj" >
<collection field="items" >
<structure name="item" choice="true" ordered="false">
<structure name="type1" map-as="type1"/>
<structure name="type2" map-as="type2"/>
</structure>
</collection>
</mapping>
<mapping class="jibx.woe.Type1" abstract="true" type-name="type1">
<value name="id" field="id"/>
</mapping>
<mapping class="jibx.woe.Type2" abstract="true" type-name="type2">
<value name="id" field="id"/>
<value name="other" field="other"/>
</mapping>
当我运行它时,我收到了这个错误:
*** Error during code generation for file 'C:\Projects\IdeaProjects\jibx-woe\src \main\config\woe-binding.xml' -
this may be due to an error in your binding or classpath, or to an error in the JiBX code ***
Internal error: Expected jibx.woe.Type1 on stack, found java.lang.Object full stack:
0: java.lang.Object
1: java.lang.Object
2: org.jibx.runtime.impl.UnmarshallingContext
所以我想我会在集合中添加一个项目类型,所以现在我的集合部分看起来像:
<collection field="items" item-type="jibx.woe.Item">
<structure name="item" choice="true" ordered="false" >
<structure name="type1" map-as="type1"/>
<structure name="type2" map-as="type2"/>
</structure>
</collection>
错误现在说:
Internal error: Expected jibx.woe.Type1 on stack, found jibx.woe.Item
full stack:
0: jibx.woe.Item
1: jibx.woe.Item
2: org.jibx.runtime.impl.UnmarshallingContext
现在我将以下方法添加到MyObj
:
public void addItem(Object type) {
items.add((Item)type);
}
并将collection
标记更改为:
<collection add-method="addItem">
与我的第一次尝试同样的错误:
Internal error: Expected jibx.woe.Type1 on stack, found java.lang.Object
full stack:
0: java.lang.Object
1: java.lang.Object
2: org.jibx.runtime.impl.UnmarshallingContext
现在我没有想法了。我怎样才能让它发挥作用?
修改
根据Archie的建议,我将绑定更改为:
<mapping name="root" class="jibx.woe.MyObj">
<structure name="item-list" >
<collection field="items">
<structure name="item" /> >
</collection>
</structure>
</mapping>
<mapping name="type1" class="jibx.woe.Type1" >
<value name="id" field="id"/>
</mapping>
<mapping name="type2" class="jibx.woe.Type2" >
<value name="id" field="id"/>
<value name="other" field="other"/>
</mapping>
</binding>
现在绑定工作没有堆栈错误(欢呼!)但现在当我从列表中得到一个项目时la:
List<Item> items = woe.getItems();
Type1 item = (Type1) items.get(0);
我明白了:
java.lang.ClassCastException: java.lang.Object cannot be cast to jibx.woe.Type1
在我上面的第二行。如果我打印对象: 的System.out.println(items.get(0));
它说: java.lang.Object@1be2d65
所以它是一个普通的对象,而不是Element或Type1(或Type2)!
我确实尝试了Archie提出的“扩展”方法,但它没有改变任何东西 - 我得到了相同的结果。
答案 0 :(得分:1)
为Item创建抽象映射。然后为Type1和Type2创建两个具体映射,每个映射都扩展Item映射。在你的items集合中,将每个元素设为一个Item(摆脱选择的东西)。
注意在JiBX中,'extends'关键字与Java类无关,它意味着'可以替代'。
限制:您必须为Type1和Type2提供两个不同的XML标记名称(例如,“type1”和“type2”),以便JiBX在解组时可以区分它们。这是您目前正在做的问题。例如,当JiBX看到一个标签时,它将如何知道要实例化哪个Java类?