Jaxb Unmarshaller以不同方式处理Long和Integer

时间:2012-05-04 12:26:26

标签: jaxb2 unmarshalling

我有一个带有单个Long变量的类,我希望我的输入xml可以被解组。当我运行unmarshal(附加单元测试)时,我在ValidationEventHandler中抛出以下错误

[severity=ERROR,message=For input string: "",locator=node=null,object=null,url=null,line=1,col=96,offset=-1]]
LinkedException: java.lang.NumberFormatException: For input string: ""

类和单元测试看起来像这样 -

@XmlRootElement
    public class Annotation {

    private Long creatorNo;

    public Long getCreatorNo() {
        return creatorNo;
    }

    public void setCreatorNo(Long creator) {
        creatorNo = creator;
    }
}

单元测试 -

public class AnnotationTest {

    @Test
    public void testUnmarshall() throws Exception {
        final String inputXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><annotation><creatorNo></creatorNo></annotation>";
        final JAXBContext jaxbContext = JAXBContext.newInstance(Annotation.class);
        final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        unmarshaller.setEventHandler(new UnmarshallerValidationEventHandler());
        final Annotation annotationObject = (Annotation)unmarshaller.unmarshal(new StringReader(inputXML));
    }
}

从它的外观来看,Jaxb不喜欢将空元素传递给Long类型。但是现在如果我在'Annotation'类中将'creatorNo'的类型更改为Integer而不是Long,则不会抛出异常,Jaxb只会创建将'creatorNo'设置为0的类。那么为什么这种不同的行为?

我追求的真实行为是我希望Jaxb将'creatorNo'视为可选项,并将其设置为NULL以及空XML元素。这可能吗?

由于

1 个答案:

答案 0 :(得分:0)

注意:我是EclipseLink JAXB (MOXy)主管,是JAXB 2 (JSR-222)专家组的成员。

您看到将空元素转换为Long的问题是JAXB RI问题,而不是JAXB问题,因为其他实现(如MOXy)正确处理此用例。您可以在以下位置记录JAXB RI的错误:

<强>变通方法

  1. 使用JAXB(JSR-222)的另一个实现,没有这个问题,这个选项是编写标准API的一大好处。
  2. 如果您使用默认的ValidationEventHandler,则会忽略此转换例外,并且您的文档将按预期解组。
  3. 使用XmlAdapter自行转换StringLong。您可以利用JAXB的DatatypeConverter来简化这一过程。
  4. 更改UnmarshallerValidationEventHandler的实施,以更好地容忍转化错误。
  5. <强> UnmarshallerValidationEventHandler

    import javax.xml.bind.ValidationEvent;
    import javax.xml.bind.ValidationEventHandler;
    
    public class UnmarshallerValidationEventHandler implements ValidationEventHandler {
    
        @Override
        public boolean handleEvent(ValidationEvent event) {
            return event.getSeverity() < ValidationEvent.FATAL_ERROR;
        }
    
    }