如何让 Jibx 在集合中添加两个实现相同接口的不同对象?

发布于 2024-09-16 10:43:55 字数 4598 浏览 5 评论 0原文

就像标题所说,我有两个实现相同接口的不同对象,我想将它们添加到同一个集合中。

我的 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 下的标记可以随时为 type1type2。它们具有相似的值,但如您所见,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>

现在绑定工作没有堆栈错误(万岁!)但是现在当我从列表中获取一个项目时:

    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)!

我确实尝试了阿奇提出的“扩展”方法,但它没有改变任何东西——我得到了相同的结果。

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:

  <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. They have similar values but, as you see, type2 has another field.

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:

  public void addItem(Object type) {
      items.add((Item)type);
   }

And changed the collection tag to:

  <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:

<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:

    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));

It says:
java.lang.Object@1be2d65

So it's a plain object, not an Element or a Type1 (or Type2) at all!

I did try the "extends" method Archie proposed, but it didn't change anything -- I got the same result.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

慵挽 2024-09-23 10:43:56

为 Item 创建抽象映射。然后为 Type1 和 Type2 创建两个具体映射,每个映射都扩展 Item 映射。在您的项目集合中,使每个元素成为一个项目(去掉选择的东西)。

请注意,在 JiBX 中,“extends”关键字与 Java 类无关,它的意思是“可以替代”。

限制:您必须为 Type1 和 Type2 提供两个不同的 XML 标记名称(例如“type1”和“type2”),以便 JiBX 在解组时可以区分它们。这是你目前所做的事情的问题。例如,当 JiBX 看到一个标签时,它如何知道要实例化哪个 Java 类?

Create an abstract mapping for Item. Then create two concrete mappings for Type1 and Type2, each extending the Item mapping. 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'.

Limitation: you will have to give Type1 and Type2 two different XML tag names (e.g., "type1" and "type2") so JiBX can distinguish them when unmarshalling. This is the problem with what you are currently doing. E.g., when JiBX sees an tag, how will it know which Java class to instantiate?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文