我在源代码中使用了Guava可选字段,我想编组一个使用Optional to xml的对象,所以我使用了JAXB。
我为此创建了XMLAdapter
:
public abstract class OptionalAdpater<T> extends XmlAdapter<T, Optional<T>> {
@Override
public Optional<T> unmarshal(T v) throws Exception {
return Optional.of(v);
}
@Override
public T marshal(Optional<T> v) throws Exception {
if (v == null) {
return null;
}
return v.isPresent() ? v.get() : null;
}
}
但是当我在课堂上使用它时
@XmlRootElement(name = "test")
public class Test {
private Optional<Integer> optionalValue = Optional.absent();
@XmlElement(name = "optional-value", type = Integer.class)
@XmlJavaTypeAdapter(type = Integer.class, value = OptionalIntegerAdapter.class)
public Optional<Integer> getOptionalValue() {
return optionalValue;
}
public void setOptionalValue(Optional<Integer> optionalValue) {
this.optionalValue = optionalValue;
}
}
JAXB失败并显示NullPointerException
。我没有得到的是,如果我不使用可选类型并且只使用盒装的Integer并且值为null
那么JAXB会跳过编组该字段,但是当我使用可选的适配器时它不起作用类型。
跟踪:
Exception in thread "main" java.lang.NullPointerException
at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$17.print(RuntimeBuiltinLeafInfoImpl.java:717)
at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$17.print(RuntimeBuiltinLeafInfoImpl.java:711)
at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$StringImpl.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:149)
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.writeLeafElement(TransducedAccessor.java:241)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:114)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:341)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:582)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:323)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:483)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:103)
答案 0 :(得分:0)
这是责任的代码:
primaryList.add(new StringImpl<Integer>(Integer.class,
createXS("int"),
createXS("unsignedShort")
) {
public Integer parse(CharSequence text) {
return DatatypeConverterImpl._parseInt(text);
}
public String print(Integer v) {
return DatatypeConverterImpl._printInt(v);
}
});
_printInt
接受int
因此,如果您返回一个空整数,则会隐式取消装箱。
为什么没有适配器/可选的工作可能是因为可选。某些地方可能会检查null
的属性。您没有null
,而是Optional
。
从我的角度来看,这是JAXB中的一个错误。运行时应在适配器转换后检查null
,而不是之前。
如何解决它 - 我认为目前唯一的方法是将Optional<Integer>
调整为字符串而不是Integer
。