2012-01-12 38 views
6

JAXBとリフレクションを使用してクライアントにコードを出力するコードをリファクタリングしていますが、現在はXMLWriterを使用しており、毎回手動でタグを作成しています。JAXBのnillable属性のデフォルト値を変更できますか?

私が抱えている問題は、クライアント側の制約のため、JavaクラスのnullフィールドのXMLに空の要素が必要なことです。

この問題は、各JAXB XmlElementアノテーションにnillable=trueを追加することで解決できますが、これは最も実用的ではありません。多くのアノテーションがあるためです。

私はnillable=trueをグローバル属性(またはデフォルト値)として設定する方法を探していました。これにより、すべての注釈にnillable属性を含める必要があることを覚えておく必要がないため、将来の同僚が作業することも容易になります。

デフォルト動作の説明に加えて、私はそれほど多くを見つけられませんでした。過去に似たような疑問を誰も投稿していないことは驚くべきことです。私が見つけたことから、デフォルト設定可能にする組み込みのサポートがあるとは思われません。これは、カスタムJAXB実装またはサードパーティJAXB実装で解決される可能性がありますか?

答えて

1

注:私はEclipseLink JAXB (MOXy)リードとJAXB 2 (JSR-222)専門家グループのメンバーです。

私はこの振る舞いを持っている拡張要求を入力したのEclipseLink JAXB(MOXY)に追加:すべての場合の回避策として

を回避

あなたマップされた文字列フィールド/プロパティがXML要素にマップされている場合、次のXmlAdapterアプローチが役に立ちます:

NullStringAdapter

このXmlAdapterAdaptedStringと呼ばれるオブジェクトとしてStringのインスタンスをマーシャリングします。 AdaptedStringには、String値と、xsi:nil属性にマップされたフィールドが含まれています。 XmlAdapterでは、Stringの値がnullかどうかに基づいて、そのフィールドの値を設定します。

package forum8841221; 

import javax.xml.bind.annotation.*; 
import javax.xml.bind.annotation.adapters.*; 

public class NullStringAdapter extends XmlAdapter<NullStringAdapter.AdaptedString, String> { 

    @Override 
    public AdaptedString marshal(String v) throws Exception { 
     AdaptedString adaptedString = new AdaptedString(); 
     if(null == v) { 
      adaptedString.nil = true; 
     } 
     adaptedString.value = v; 
     return adaptedString; 
    } 

    @Override 
    public String unmarshal(AdaptedString v) throws Exception { 
     return v.value; 
    } 

    public static class AdaptedString { 

     @XmlAttribute(namespace="http://www.w3.org/2001/XMLSchema-instance") 
     public Boolean nil; 

     @XmlValue 
     @XmlJavaTypeAdapter(VoidStringAdapter.class) 
     public String value; 

    } 

    public static class VoidStringAdapter extends XmlAdapter<String, String> { 

     @Override 
     public String marshal(String v) throws Exception { 
      return v; 
     } 

     @Override 
     public String unmarshal(String v) throws Exception { 
      return v; 
     } 

    } 

} 

パッケージ情報

私たちは、このXmlAdapterは、パッケージレベルでXmlAdapterを登録することで、このパッケージのすべてのマップされたStringフィールド/プロパティに適用することを登録することができます。以下は

@XmlJavaTypeAdapter(value=NullStringAdapter.class, type=String.class) 
@XmlSchema(xmlns={@XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")}) 
package forum8841221; 

import javax.xml.bind.annotation.adapters.*; 
import javax.xml.bind.annotation.*; 

ルート

私はこの例で使用したドメインクラスです。これは、そのうちの一つが(真= NULLに)@XmlElementと注釈されている、いくつかの文字列の特性を有している

package forum8841221; 

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Root { 

    private String a; 
    private String b; 
    private String c; 
    private String d; 

    public String getA() { 
     return a; 
    } 

    public void setA(String a) { 
     this.a = a; 
    } 

    public String getB() { 
     return b; 
    } 

    public void setB(String b) { 
     this.b = b; 
    } 

    public String getC() { 
     return c; 
    } 

    public void setC(String c) { 
     this.c = c; 
    } 

    @XmlElement(nillable=true) 
    public String getD() { 
     return d; 
    } 

    public void setD(String d) { 
     this.d = d; 
    } 

} 

デモ

package forum8841221; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Root.class); 

     Root root = new Root(); 
     root.setB("B"); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(root, System.out); 
    } 

} 

出力

<?xml version="1.0" encoding="UTF-8"?> 
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <a xsi:nil="true"/> 
    <b>B</b> 
    <c xsi:nil="true"/> 
    <d xsi:nil="true"/> 
</root> 
関連する問題