2012-01-12 2 views
6

JAXB 및 반사를 사용하여 클라이언트에 코드를 출력하도록 일부 코드를 리팩토링하고 있습니다. 현재 XMLWriter를 사용하고 매번 수동으로 태그를 생성하고 있습니다.JAXB에서 nillable 속성의 기본값을 변경할 수 있습니까?

문제는 클라이언트 측 제약으로 인해 Java 클래스의 null 필드에 XML 요소가 비어 있어야한다는 것입니다.

주석을 많이 가지고 있기 때문에이 문제는 각각의 JAXB XmlElement 주석에 nillable=true을 추가하여 해결할 수 있습니다. 이는 실용적이지 않습니다.

nillable=true을 글로벌 속성 (또는 기본값)으로 설정하는 방법을 찾고 싶습니다. 또한 모든 주석에 nillable 속성을 포함해야한다는 것을 기억할 필요가 없으므로 향후 동료가 쉽게 작업 할 수 있습니다.

기본 동작에 대한 설명 외에도 많은 것을 찾지 못했습니다. 나는 그 누구도 과거에 비슷한 질문을 게시 한 것이 놀랍다. 내가 찾은 바에 따르면 기본 설정을 구성 할 수있는 기본 제공 지원이 없다고 생각됩니다. 사용자 정의 JAXB 구현 또는 제 3 자 JAXB 구현으로 해결할 수있는 것입니까?

답변

1

참고 :은 내가 EclipseLink JAXB (MOXy) 리드와 JAXB 2 (JSR-222) 전문가 그룹의 구성원입니다.

내가이 동작을 할 수있는 개선 요청을 입력 한 EclipseLink가 JAXB (목시)에 추가 : 모든 경우 주위 작품으로

를 해결

당신의 매핑 된 문자열 필드/속성이 XML 요소에 매핑되면 다음 XmlAdapter 접근 방식을 사용할 수 있습니다.

객체가 AdaptedString 전화로이 XmlAdapterString의 인스턴스를 마샬링합니다

NullStringAdapter. AdaptedStringString 값과 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.*; 

루트 아래

내가이, 예를 들면 사용한 도메인 클래스입니다.그것은 그들 중 하나 (nillable로 = TRUE) @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> 
관련 문제