java - JAXB 空元素解码

标签 java xml exception jaxb

问题出在下面:

我得到了里面有空元素的 soap 响应(例如 ... <someDate /> ... ) 结果当 JAXB 想要解析这个元素时抛出异常 而不是使用 null 设置适当的字段值(value)。

如何配置 JAXB 将空元素视为 null ? 我们可以仅使用 JAXB 来做到这一点吗(不使用某些第三方解决方法)

最佳答案

基础问题

String 不是 xsd:date 类型的有效值。为了对 XML 模式有效,可选元素应表示为不存在的节点。


为什么基础问题会影响您

所有 JAXB 实现都将识别空 String 不是 xsd:date 的有效值。他们通过将其报告给 ValidationEventHandler 的实例来做到这一点。您可以通过执行以下操作自己查看:

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    unmarshaller.setEventHandler(new ValidationEventHandler() {

        @Override
        public boolean handleEvent(ValidationEvent event) {
            System.out.println(event);
            return true;
        }
    });

您正在使用的 JAX-WS 实现利用了 EclipseLink MOXy作为 JAXB 提供者。在您使用 MOXy 的版本中,当遇到严重性为 ERRORValidationEvent 而不是像引用实现那样的 FATAL_ERROR 时,默认情况下会抛出异常.这已在以下错误中得到修复:


变通

如果您直接使用 JAXB API,您可以简单地覆盖默认的 ValidationEventHandler。在 JAX-WS 环境中,XmlAdapter 可用于提供自定义转换逻辑。我们将利用 XmlAdapter 来覆盖如何处理与 Date 之间的转换。

XmlAdapter(日期适配器)

import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class DateAdapter extends XmlAdapter<String, Date>{

    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public Date unmarshal(String v) throws Exception {
        if(v.length() == 0) {
            return null;
        }
        return dateFormat.parse(v);
    }

    @Override
    public String marshal(Date v) throws Exception {
        if(null == v) {
            return null;
        }
        return dateFormat.format(v);
    }

}

Java 模型(根)

使用 @XmlJavaTypeAdapter 注释引用 XmlAdapter。如果您希望此 XmlAdapter 应用于 Date 的所有实例,您可以在包级别注册它(参见:http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html)。

import java.util.Date;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlSchemaType(name = "date")
    @XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class)
    private Date abc;

    @XmlSchemaType(name="date")
    @XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class)
    private Date qwe;

}

演示代码

下面是一个独立示例,您可以运行以查看一切正常。

jaxb.properties

在使用 MOXy 作为 JAXB 提供程序的独立示例中,您需要在与域模型相同的包中包含一个名为 jaxb.propeties 的文件,其中包含以下条目(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html) .

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

输入.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <abc></abc>
    <qwe>2013-09-05</qwe>
</root>

演示

import java.io.File;
import javax.xml.bind.*;

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum18617998/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

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

}

输出

请注意,在编码的 XML 中,为空的 Date 字段被编码为不存在的元素(请参阅:http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html)。

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <qwe>2013-09-05</qwe>
</root>

关于java - JAXB 空元素解码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18921196/

相关文章:

java - 在derby数据库中存储数组

java - 为什么我不能从事件监听器调用方法,但可以在类的其他地方调用方法?

java - 如何在 JFreeChart 中实现居中的 FlowArrangement?

java - 如何向 @XmlElementWrapper ArrayList 添加属性?

Java 如何比较 XML 数据与文件扩展名

java - 如何使Spring应用程序的业务逻辑用户可配置?

xml - 竖线 (|) Unicode 替换

java.lang.Exception 与滚动您自己的异常

c++ - 什么时候应该抛出异常?

c# - 倾斜动画无法制作动画