5

クラスに必要なフィールド名がある場所Rootを含むルート要素クラスを記述するスキーマがあると仮定します。List<Entry>Entry

コードでの表示は次のとおりです。

@XmlRootElement 
class Root{
  @XmlElement(name="entry")
  public List<Entry> entries = Lists.newArrayList();
}

@XmlRootElement 
class Entry{
  @XmlElement(name="name",required=true)
  public String name;
}

アンマーシャリング用に次の XML を指定すると、次のようになります。

<root>
  <entry>
    <name>ekeren</name>
  </entry>
  <entry>
  </entry>
</root>

2 番目のエントリに名前が含まれていないため、問題があります。したがって、 unmarshall は を生成しnullます。

Root「良い」エントリのみを含むオブジェクトを非整列化するように JAXB をカスタマイズする方法はありますか?

4

1 に答える 1

5

空のエントリを処理する魔法の afterUnmarshal メソッドを追加できます。

@XmlRootElement 
class Root{
  @XmlElement(name="entry")
  public List<Entry> entries = Lists.newArrayList();

  void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) {
    Iterator<Entry> iter = entries.iterator();
    while (iter.hasNext()) {
      if (iter.next().name == null) iter.remove();
    }
  }
}

編集:

これがあなたに適しているかどうかはわかりませんが、役立つかもしれません。結果を修正/検証する必要があるすべてのオブジェクトが afterUnmarshal(..) で利用できるわけではない場合など、Pacher を使用することもできます。

すべての解析が完了した後、UnmarshallingContext によって実行されます。主に前方 IDREF を解決するために使用されますが、任意のアクションを実行できます。(javadoc)

次に例を示します。

@XmlRootElement 
class Entry{
  @XmlElement(name="name",required=true)
  public String name;

  private boolean isValidEntry() {
    return name != null;
  }

  void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) {
    if (!isValidEntry()) {
      // entry not yet added to parent - use a patcher
      UnmarshallingContext.getInstance().addPatcher(new Patcher() {
        public void run() throws SAXException {
          ((Root)parent).removeEntry(this);
        }
      });
    }
  }
}

ただし、Sun 専用の API であるだけでなく、あまり乱用するつもりはありません。

しかし、マーシャリングされたオブジェクト自体のコードの一部ではない構成可能なものを実際に調べている場合。アンマーシャリング後に何かを見るのが最善かもしれません。Bean Validation (JSR 303)は、たとえばHibernate Validatorを使用するなど、あなたにぴったりではないのではないかと思います(名前に怖がらないでください。使用するために Hibernate ORM は必要ありません)。私はそれを自分で使用したことはありませんが、検証に (新しい) 標準を使用することは理にかなっていると思いませんか?

于 2010-05-04T15:18:09.407 に答える