Java JAXB 空元素解组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18921196/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 12:31:38  来源:igfitidea点击:

JAXB empty element unmarshalling

javaxmlexceptionjaxb

提问by ikos23

The problem is in the following :

问题在于:

I get the soap response with empty element inside (e.g. ... <someDate /> ...) and as a result exception is being throwed when JAXB wants to parse this element instead to set the appropriate field with nullvalue.

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

How to configure JAXB to treat empty elements as null ? Can we do this with JAXB only (not using some third-party workarounds)

如何配置 JAXB 以将空元素视为 null ?我们可以仅使用 JAXB 来执行此操作吗(不使用某些第三方解决方法)

采纳答案by bdoughan

Base Problem

基本问题

Empty Stringis not a valid value for the xsd:datetype. To be valid with the XML schema an optional element should be represented as an absent node.,

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



Why the Base Problem is Impacting You

为什么基本问题会影响你

All JAXB implementations will recognize that empty Stringis not a valid value for xsd:date. They do this by reporting it to an instance of ValidationEventHandler. You can see this yourself by doing the following:

所有 JAXB 实现都会认识到 emptyString不是 的有效值xsd:date。他们通过将其报告给ValidationEventHandler. 您可以通过执行以下操作自行查看:

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

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

The implementation of JAX-WS you are using, leverages EclipseLink MOXyas the JAXB provider. And in the version you are using MOXy will by default throw an exception when a ValidationEventof severity ERRORis encountered instead of FATAL_ERRORlike the reference implementation. This has since been fixed in the following bug:

您正在使用的 JAX-WS 实现利用EclipseLink MOXy作为 JAXB 提供者。在您使用的版本中,MOXy 默认会在遇到ValidationEvent严重性时抛出异常,ERROR而不是FATAL_ERROR像参考实现那样。此问题已在以下错误中得到修复:



Work Around

解决

If you are using the JAXB APIs directly you could simply override the default ValidationEventHandler. In a JAX-WS environment a XmlAdaptercan be used to provide custom conversion logic. We will leverage an XmlAdapterto override how the conversion to/from Dateis handled.

如果您直接使用 JAXB API,您可以简单地覆盖默认的ValidationEventHandler. 在 JAX-WS 环境中,aXmlAdapter可用于提供自定义转换逻辑。我们将利用 anXmlAdapter来覆盖转换到/从Date的处理方式。

XmlAdapter (DateAdapter)

XmlAdapter (DateAdapter)

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 Model (Root)

Java 模型(根)

The XmlAdapteris referenced using the @XmlJavaTypeAdapterannotation. If you wish this XmlAdapterto apply to all instances of Dateyou can register it at the package level (see: http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html).

XmlAdapter使用引用的@XmlJavaTypeAdapter注释。如果您希望这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;

}


Demo Code

演示代码

Below is a standalone example you can run to see that everything works.

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

jaxb.properties

jaxb.properties

In a standalone example to use MOXy as your JAXB provider you need to include a file called jaxb.propetiesin the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).

在使用 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

input.xml

输入文件

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

Demo

演示

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);
    }

}

Output

输出

Note that in the marshalled XML the Datefield that was null was marshalled as an absent element (see: http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html).

请注意,在编组的 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>