Java JAXB XmlIDREF和映射/列表

Java JAXB XmlIDREF和映射/列表,java,xml,jaxb,jersey,unmarshalling,Java,Xml,Jaxb,Jersey,Unmarshalling,我有一个相当复杂的数据结构,似乎无法正确地解组 @XmlRootElement class Tree { @XmlID private String id; @XmlJavaTypeAdapter(type=TreeFooAdapter.class) Map<Tree, Foo> fooMap; } class Foo { @XmlID private String id; } 我有两棵独立的树。每个树中的两个节点可以配对并与Foo实例关联。fooMap

我有一个相当复杂的数据结构,似乎无法正确地解组

@XmlRootElement
class Tree {
  @XmlID
  private String id;

  @XmlJavaTypeAdapter(type=TreeFooAdapter.class)
  Map<Tree, Foo> fooMap;
}

class Foo {
  @XmlID
  private String id;
}
我有两棵独立的树。每个树中的两个节点可以配对并与Foo实例关联。fooMap用于跟踪给定树节点与哪些其他节点配对,以及Foo结果的实例

TreeFooAdapter非常简单,但请注意,它使用ID引用:

public class TreeFooAdapter extends XmlAdapter<TreeFooAdapter.MapType, Map<Tree, Foo>> {
  public static class MapType {
    public static class MapEntry {
      @XmlAttribute
      @XmlIDREF
      public Tree key;
      @XmlAttribute
      @XmlIDREF
      public Foo value;
    }
    // etc...
  }

  // Standard drill for marshal/unmarshal...
}
问题是:转发引用不起作用!在解组时,XML中最先出现的树在其fooMap中都会有空键。因为这两棵树相互引用,所以我无法改变XML的顺序来解决这个问题

我尝试了一种黑客方法,其中我有一个私有方法来获取/设置列表,但它产生了相同的结果


当转发ID引用包含在映射或列表中时,为什么JAXB无法处理它们?我如何解决这个问题?

我发现了一个可怕的、可怕的、丑陋的解决方法,灵感来自。我基本上将PhoneNumberDatapter类推广到处理任何可识别的对象,即具有唯一ID,即Foo和Tree。我没有AdaptedPhoneNumber类,而是有一个ObjectWrapper bean,它要么包含第一次遇到时要包装的实际对象,要么在后续遇到时仅包含其ID。TreeFooAdapter中的MapEntry类没有XmlIDREFs,而是将我的IdentifiableAdapter指定为XmlJavaTypeAdapter


这就产生了糟糕透顶、不可读的XML,但至少它是有效的。尽管如此,这似乎是JAXB中的一个bug:经过一些痛苦的调试后,我仍然无法弄清楚为什么XmlIDREF在经过修改的Map类中不工作。

我尝试了另一种似乎有效的方法。诀窍包括以下几点:

创建一个私有getter/setter对,将fooMap转换为treefoadapter.MapType 向treefoadapter.MapType添加一个XmlID,并用XmlIDREF注释getter 维护treefoadapter.MapType的静态实例集 编组时,在编组Tree和Foo的所有实例之后,还要编组实例集。
这产生了更干净的XML:树是用简单的IDREF为其fooMaps进行编组的,XML文件的末尾只是一长串TreeFooAdapter.MapTypes,它们本身就是IDREF对的列表。如果多次封送/解封送,则必须小心清理静态实例集。

…尽管在为我的单元测试添加了更多深度后,我发现这也不太管用…: