web-dev-qa-db-ja.com

nullフィールドを使用したJAXBマーシャリング

これは非常に単純なリクエストですが、私はそれを行う方法を見つけられませんでした。

私は基本的にJAXBでロールを設定しようとしています。これは、出力でnullフィールドを無視するのではなく、nullフィールドが検出されるたびに空の値に設定するというものです。クラスの場合:

@XMLRootElement
Class Foo {
   Integer num;
   Date date;
….
}

日付フィールドがnullの場合、これがXMLファイルにマーシャリングされると、出力にはその要素が含まれません。私がしたいのは、出力にすべてのフィールドを含めることです。そして、それらがnullの場合、それらを-空白で置き換えます。したがって、出力は次のようになります。

<foo>
  <num>123</num>
  <date></date>
</foo>

おかげで、

ヤルペシ。

48
Jalpesh

答えてくれてありがとう。

クリス・デイル-あなたのアプローチを試みましたが、私が望んでいたことは本当にしませんでした。 JAXBは、フィールドのデフォルト値を定義しているにもかかわらず、まだnull値を無視していました。

Jerseyフォーラムの誰かがドキュメントのセクションを教えてくれた後、私はその答えに出くわしました 2.2.12.8 No Value

基本的に、私がしなければならなかったのは、私のフィールドに以下を追加することだけでした:

@XmlElement(nillable = true) 

それを追加すると、JAXBはこれらのフィールドをXMLにマーシャリングするときに次のように表示します。

...
<num>5</num>
<date xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
....
39
Jalpesh

しかし、しかし...空の文字列は日付の有効な字句表現ではないため、それはできません。つまり、日付フィールドの値が空のXMLドキュメントを生成した場合、適切に検証されません。

言い換えると、date要素のminOccursの値が1以上で、nillableではない場合、絶対に(1つ以上の)日付が必要です。または空白、またはその他の非値)。

4

他の回答に示されているように、有効な日付ではないため無効です。特別に処理したい(と同じ)同様の問題がありました。 nullは使用できないため、JAXBのデフォルト値メカニズムを使用できます。以下は、何も指定されていない場合のデフォルト値です。コードを介してこの特別な日付を検出し、この例外ケースを処理できます。

@XmlElement(defaultValue="1970-01-01T00:00:00.0-00:00")

したがって、日付値を検出して空にすることは可能ですが、nullを使用してそれを行うことはできません。

2
Chris Dail

MOXyでは、jsonProviderがJAXBに対してどのようにジョブを実行する必要があるかを指定できます。

JAX-RSを実行するときは、Applicationから派生したクラスに次のコードを追加します

Tomcat 7でこのコードを使用すると、良い結果が得られました。 (eclipselink 2.4.1)

@ApplicationPath("/rest")
public class RestApplication extends Application
{

  ...

 public Set< Object> getSingletons()
  {

    HashSet<Object> set = new HashSet<Object>(1);
    set.add( newMoxyJsonProvider());

    return set;
  }


 public static MOXyJsonProvider newMoxyJsonProvider()
  {

    MOXyJsonProvider result = new MOXyJsonProvider();

    //result.setAttributePrefix("@");
    result.setFormattedOutput( false);
    result.setIncludeRoot( false);
    result.setMarshalEmptyCollections( true);
    //result.setValueWrapper("$");

    return result;
  }

ただし、Glassfish 3.1.2およびWAS 8.5では、newMoxyJsonProvider()は必要ありませんが、JAXBプロバイダーはサーバーによって構成されます。 MOXyに付属するGlassfishの場合、null値で同じ問題が発生しました。まだチェックしませんでしたが、可能であれば、アプリケーションサーバーレベルでJAXBを構成することに答えがあると思います。

1
Jan Serneels

これを試して:

marshal.setListener(new MarshallerListener());

public class MarshallerListener extends Marshaller.Listener {

    public static final String BLANK_CHAR = "";

    @Override
    public void beforeMarshal(Object source) {
        super.beforeMarshal(source);
        Field[] fields = source.getClass().getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            try {
                if (f.getType() == String.class && f.get(source) == null) {
                    f.set(source, BLANK_CHAR);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}
0
xudd