[英]How do I get Jibx to add two different objects implementing the same interface in a collection?
Like the title says, I have two different objects that implement the same interface and I want to add them to the same collection. 就像标题中所说的,我有两个不同的对象实现相同的接口,我想将它们添加到同一集合中。
My XML looks like: 我的XML看起来像:
<root>
<item-list>
<item>
<type1>
<id>1</id>
</type1>
</item>
<item>
<type2>
<id>2</id>
<other>1</other>
</type2>
</item>
</item-list>
</root>
The tag under item
can either be type1
or type2
at any time. item
下的标签可以随时为type1
或type2
。 They have similar values but, as you see, type2
has another field. 它们具有相似的值,但是,如您所见,
type2
还有另一个字段。
My Interface is: 我的界面是:
public interface Item {
public String getID();
}
My three classes: 我的三堂课:
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;
}
}
My binding looks like this: 我的绑定看起来像这样:
<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>
And when I run it, I get the this error: 当我运行它时,出现以下错误:
*** 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
So I thought I add an item type to the collection, so now my collection section looks like: 所以我想我将一个项目类型添加到集合中,所以现在我的集合部分如下所示:
<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>
And the error now says: 现在错误显示:
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
So now I add the following method to MyObj
: 所以现在我将以下方法添加到
MyObj
:
public void addItem(Object type) {
items.add((Item)type);
}
And changed the collection
tag to: 并将
collection
标签更改为:
<collection add-method="addItem">
And get same same error as my first attempt: 并得到与我的第一次尝试相同的错误:
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
And now I'm out of ideas. 现在我没主意了。 How can I get this to work?
我该如何工作?
EDIT 编辑
Based on Archie's recommendation below, I changed my binding to: 根据以下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>
And now the binding works without stack errors (hurray!) but now when I get a item from my list a la: 现在绑定可以正常工作而不会出现堆栈错误(万岁!),但是现在当我从列表中得到一个项目时,la:
List<Item> items = woe.getItems();
Type1 item = (Type1) items.get(0);
I get: 我得到:
java.lang.ClassCastException: java.lang.Object cannot be cast to jibx.woe.Type1
On my second line above. 在上面的第二行。 If I print the object: System.out.println(items.get(0));
如果我打印对象:System.out.println(items.get(0));
It says: java.lang.Object@1be2d65 它说:java.lang.Object@1be2d65
So it's a plain object, not an Element or a Type1 (or Type2) at all! 因此,它是一个普通对象,根本不是Element或Type1(或Type2)!
I did try the "extends" method Archie proposed, but it didn't change anything -- I got the same result. 我确实尝试了Archie提出的“扩展”方法,但没有任何改变-我得到了相同的结果。
Create an abstract mapping for Item. 为Item创建一个抽象映射。 Then create two concrete mappings for Type1 and Type2, each extending the Item mapping.
然后为Type1和Type2创建两个具体的映射,每个映射都扩展了Item映射。 In your items collection, make each element an Item (get rid of the choice stuff).
在您的项目集合中,使每个元素成为一个项目(摆脱选择的东西)。
Note in JiBX the 'extends' keyword has nothing to do with Java classes, it means 'can be substituted for'. 注意,在JiBX中,“ extends”关键字与Java类无关,它表示“可以代替”。
Limitation: you will have to give Type1 and Type2 two different XML tag names (eg, "type1" and "type2") so JiBX can distinguish them when unmarshalling. 限制:您将不得不给Type1和Type2两个不同的XML标签名称(例如,“ type1”和“ type2”),以便JiBX在解组时可以区分它们。 This is the problem with what you are currently doing.
这是您当前正在做的问题。 Eg, when JiBX sees an tag, how will it know which Java class to instantiate?
例如,当JiBX看到一个标签时,它将如何知道要实例化哪个Java类?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.