2016-08-05 3 views
0

XMLをPOJOにアンマーシャリングするときに、本当に 'missing'と 'null'を区別できる必要があります。私はOptional<BigInteger>フィールドを持っているとOptionalタイプ用のアダプタ:私が欲しいものMoxy JAXBと 'missing'と明示的nullを区別する

public abstract class OptionalAdapter<T> extends XmlAdapter<T, Optional<T>> { 

    @Override 
    public Optional<T> unmarshal(T value) throws Exception { 
     log.debug("Unmarshalling value: {}", value); 

     if(value == null) { 
      log.debug("Value is null, returning Optional.empty()"); 
      return Optional.empty(); 
     } else { 
      log.debug("Value is not null, returning an optional holding the value"); 
      return Optional.of(value); 
     } 
    } 

    @Override 
    public T marshal(Optional<T> value) throws Exception { 
     if (value == null) { 
      return null; 
     } 

     return value.isPresent() ? value.get() : null; 
    } 
} 

はセッターを呼び出さないために、このOptional<BigInteger>フィールドのノードが欠落しているXMLのために、しかし、どのノードを持たないすべてのXMLのためでありますフィールドがOptional.empty()に設定されるセッターを呼び出すために空(私は明示的なnullを表すためにこれを選択しました)です。

@XmlNullPolicy(emptyNodeRepresentsNull = true, nullRepresentationForXml = XmlMarshalNullRepresentation.EMPTY_NODE, 
     isSetPerformedForAbsentNode =false) 
private Optional<BigInteger> field; 

フィールドが設定されていないとnullのまま:私はこれを行う場合は

、明示的なヌルのためのケースでは動作しません。 isSetPerformedForAbsentNodetrueに設定すると、ノードが見つからない場合のケースが機能しません。セッターはnullで呼び出され、フィールドはOptional.empty()に設定されます。何らかの方法がありますが、私はJAXBの実装をいくつか設定して、私が望むものを作ることができますか? Absentとnullは非常に異なるものを意味し、私はその違いを伝えることができる必要があります。

答えて

1

要素参照とJaxBのMoxy実装を使用する必要がありました。私は2つのフィールド、POJOとのプロパティの実際の値であるOptional<BigInteger>フィールドを宣言した後

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

は私が定義され、このプロパティを使用して、私のPOJOのためのパッケージで jaxb.propertiesファイルを配置しました値が明示的にnullかXMLソースから欠落しているかどうかを判断するために使用する要素参照フィールドです。

private Optional<BigInteger> parentGroupId; 
private JAXBElement<BigInteger> parentGroupIdElementRef; 

マイOptionalアダプタクラス:

public abstract class OptionalAdapter<T> extends XmlAdapter<T, Optional<T>> { 

    @Override 
    public Optional<T> unmarshal(T value) throws Exception { 
     return Optional.of(value); 
    } 

    @Override 
    public T marshal(Optional<T> value) throws Exception { 
     return value.isPresent() ? value.get() : null; 
    } 
} 

要素参照のための私のハンドラ:POJOで

@XmlRegistry 
public class ParentGroupIdXmlElementRef { 

    @XmlElementDecl(name="parentGroupId") 
    public JAXBElement<BigInteger> createFooJAXBElement(final BigInteger value) { 
     return new JAXBElement<>(new QName("parentGroupId"), BigInteger.class, value); 
    } 
} 

私のゲッターとセッター:今すぐすべての

@XmlElement(required = false, nillable = true) 
@XmlJavaTypeAdapter(OptionalBigIntegerAdapter.class) 
@XmlNullPolicy(isSetPerformedForAbsentNode = false, nullRepresentationForXml = XmlMarshalNullRepresentation.XSI_NIL) 
@Override 
public void setParentGroupId(final Optional<BigInteger> parent) { 
    log.debug("Parent setter called: {}", parent); 
    if (parent != null && parent.isPresent() && parent.get().signum() == -1) { 
     throw log.throwing(new IllegalArgumentException("Cannot specify a parent group ID less than 0")); 
    } 
    this.parentGroupId = parent; 
    //this.isParentIdMissing = false; 

    if (parent == null) { 
     parentGroupIdElementRef = null; 
    } else if (parent.isPresent() && parentGroupIdElementRef == null) { 
     parentGroupIdElementRef = new ParentGroupIdXmlElementRef().createFooJAXBElement(parent.get()); 
    } else if(parentGroupIdElementRef == null) { 
     parentGroupIdElementRef = new ParentGroupIdXmlElementRef().createFooJAXBElement(null); 
     parentGroupIdElementRef.setNil(true); 
    } 
} 

@XmlElement(required = false, nillable = true) 
@XmlJavaTypeAdapter(OptionalBigIntegerAdapter.class) 
@XmlNullPolicy(isSetPerformedForAbsentNode = false, nullRepresentationForXml = XmlMarshalNullRepresentation.XSI_NIL) 
@Override 
public @Nullable @Nonnegative Optional<BigInteger> getParentGroupId() { 
    return parentGroupId; 
} 

@XmlElementRef(name="parentGroupId", required=false) 
public void setParentGroupIdElementRef(final JAXBElement<BigInteger> elementRef) { 
    log.debug("Setting element reference for parent ID: {}", elementRef); 
    this.parentGroupIdElementRef = elementRef; 

    if(parentGroupIdElementRef == null) { 
     setParentGroupId(null); 
    } else if(parentGroupIdElementRef.isNil()) { 
     setParentGroupId(Optional.empty()); 
    } else { 
     setParentGroupId(Optional.of(elementRef.getValue())); 
    } 
} 

@XmlElementRef(name="parentGroupId", required=false) 
public JAXBElement<BigInteger> getParentGroupIdElementRef() { 
    log.debug("Getting Element reference: {}", parentGroupIdElementRef); 
    return this.parentGroupIdElementRef; 
} 

私のユニットテストは合格する。非ヌル、ヌル、欠損はすべて適切に処理されます。

関連する問題