简体   繁体   English

JAXB XmlIDREF和地图/列表

[英]JAXB XmlIDREF and Maps/Lists

I have a fairly complicated data structure that I can't seem to get to unmarshal correctly. 我有一个相当复杂的数据结构,似乎无法正确解组。

@XmlRootElement
class Tree {
  @XmlID
  private String id;

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

class Foo {
  @XmlID
  private String id;
}

I have TWO separate trees. 我有两棵单独的树。 Two nodes (one from each tree) can be paired and associated with an instance of Foo. 两个节点(每棵树一个)可以配对并与Foo实例关联。 fooMap is used to keep track of what other nodes a given tree node has been paired with, and what instance of Foo results. fooMap用于跟踪给定树节点已与哪些其他节点配对以及Foo结果的实例。

The TreeFooAdapter is pretty straightforward, but note that it uses ID refs: 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...
}

THE PROBLEM : Forward references don't work! 问题 :前向引用不起作用! When unmarshalling, whichever Tree comes first in the XML will have null keys in its fooMap. 取消编组时,XML中的第一个树将在其fooMap中具有空键。 Since the two trees reference each other, there's no way that I could change the order of the XML to get around this. 由于这两个树相互引用,因此我无法更改XML的顺序来解决此问题。

I've tried a hack wherein I have a private method to get/set a List<TreeFooMapEntry> , but it produces the same result. 我尝试了一种黑客方法,其中我有一个私有方法来获取/设置List<TreeFooMapEntry> ,但是它会产生相同的结果。

Why is JAXB unable to handle forward ID references when they're contained in a Map or List, and how can I resolve this? 当JAXB包含在Map或List中时,为什么它们无法处理正向ID引用,我该如何解决呢?

I've found a (horrible, awful, ugly) workaround, inspired by this . 我已经找到了(可怕的,可怕的,丑陋的)的解决方法,启发这个 I basically generalized the PhoneNumberAdapter class to work with anything "Identifiable", ie having a unique ID (ie, both Foo and Tree). 我基本上使PhoneNumberAdapter类可以与任何“可识别的”东西一起工作,即具有唯一的ID(即Foo和Tree)。 Instead of having an AdaptedPhoneNumber class, I have an ObjectWrapper bean that will either contain the actual object being wrapped (when first encountered), or just its ID (on subsequent encounters). 我没有一个AdaptedPhoneNumber类,而是有一个ObjectWrapper Bean,它将包含被包装的实际对象(首次遇到时),或者仅包含其ID(在后续遇到时)。 The MapEntry class in TreeFooAdapter, instead of having XmlIDREFs, instead specifies my IdentifiableAdapter as the XmlJavaTypeAdapter. TreeFooAdapter中的MapEntry类没有XmlIDREF,而是将IdentifiableAdapter指定为XmlJavaTypeAdapter。

This creates god-awful, unreadable XML, but at least it works. 这会创建令人讨厌的,无法读取的XML,但至少可以正常工作。 Still, this seems like a bug in JAXB: after some painful debugging, I still haven't been able to figure out why XmlIDREF doesn't work when inside of an adapted Map class. 仍然,这似乎是JAXB中的错误:经过一些痛苦的调试之后,我仍然无法弄清楚为什么XmlIDREF在适应的Map类中时不起作用。

I tried another hack that appears to work this time. 我这次尝试了另一种似乎有效的黑客手段。 The trick involves the following: 诀窍涉及以下内容:

  • create a private getter/setter pair that transforms fooMap into TreeFooAdapter.MapType 创建一个私有的getter / setter对,将fooMap转换为TreeFooAdapter.MapType
  • add an XmlID to TreeFooAdapter.MapType, and annotate the getter with XmlIDREF 将XmlID添加到TreeFooAdapter.MapType,并使用XmlIDREF注释getter
  • maintain a static Set of instances of TreeFooAdapter.MapType 维护TreeFooAdapter.MapType的静态实例集
  • when marshalling, AFTER marshalling all the instances of Tree and Foo, also marshal the Set of instances. 封送时,封送Tree和Foo的所有实例后,还封送实例集。

This produces much cleaner XML: the Trees are marshalled with simple IDREFs for their fooMaps, and the end of the XML file is just a long list of TreeFooAdapter.MapTypes, which are themselves just lists of pairs of IDREFs. 这样可以生成更清晰的XML:将树和它们的fooMap组合在一起,使用简单的IDREF进行编排,而XML文件的末尾只是TreeFooAdapter.MapTypes的一长串列表,而TreeFooAdapter.MapTypes本身就是成对的IDREF。 You have to be careful to clean up the static Set of instances if you marshal/unmarshal more than once. 如果封送/解封不止一次,则必须小心清除静态的实例集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM