【问题标题】:Convert nil="true" to null during unmarshal operation在解组操作期间将 nil="true" 转换为 null
【发布时间】:2012-09-20 19:31:10
【问题描述】:

我从服务器接收 XML,其架构几乎将每个元素都指定为:

<xs:element name="myStringElementName" type="xs:string" nillable="true" minOccurs="0"/>
<xs:element name="myIntElementName" type="xs:int" nillable="true" minOccurs="0"/>

我正在尝试找到一种干净的方法来将收到的每个标记为 xsi:nil="true" 的元素在解组为 JAXB 对象时转换为 null。所以是这样的:

<myIntElementName xsi:nil="true" />

应该导致我的 JAXB 对象具有值为 null 的 myIntElementName 属性,而不是具有设置为 true 的 nil 属性(或任何类似的东西)的 JAXBElement 对象。我无法控制向我发送使用 nillable 属性的 XML 的系统,因此我需要在收到它时自行转换它。

【问题讨论】:

    标签: java xml jaxb jaxb2 xml-nil


    【解决方案1】:

    @XmlElement(nillable=true)

    您只需在您的字段/属性上指定 @XmlElement(nillable=true) 即可获得此行为:

    @XmlElement(nillable=true)
    private String foo;
    

    从 XML 架构生成

    如果您从 XML 模式开始,我将在下面演示如何生成此映射。

    XML 架构 (schema.xsd)

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="foo">
            <xs:complexType>
                <xs:sequence>
                    <xs:element name="myStringElementName" type="xs:string"
                        nillable="true" minOccurs="0" />
                    <xs:element name="myIntElementName" type="xs:int"
                        nillable="true" minOccurs="0" />
                </xs:sequence>
            </xs:complexType>
        </xs:element>
    </xs:schema>
    

    为什么你会得到 JAXBElement 类型的属性

    在您的模型中生成了JAXBElement 类型的属性,因为您有一个可空元素,即minOccurs="0"。使用JAXBElement 允许模型区分缺少的元素(属性为空)和带有nil="true" 的元素的存在(设置了nil 标志的JAXBElement)。

    <xs:element name="myStringElementName" type="xs:string"
                            nillable="true" minOccurs="0" />
    

    外部绑定文件 (binding.xml)

    可以指定一个外部绑定文件来告诉 JAXB 实现不要生成任何 JAXBElement 类型的属性。请注意,这将使 JAXB 无法往返所有 XML 文档。

    <?xml version="1.0" encoding="UTF-8"?>
    <jaxb:bindings version="2.0"
                   xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
        <jaxb:bindings>
            <jaxb:globalBindings generateElementProperty="false"/>
        </jaxb:bindings>
    </jaxb:bindings>
    

    XJC 通话

    以下是如何利用 XJC 调用中的外部绑定文件的示例

    xjc -b binding.xml schema.xsd
    

    生成模型(Foo)

    生成的模型如下所示:

    import javax.xml.bind.annotation.*;
    
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "myStringElementName",
        "myIntElementName"
    })
    @XmlRootElement(name = "foo")
    public class Foo {
    
        @XmlElement(nillable = true)
        protected String myStringElementName;
        @XmlElement(nillable = true)
        protected Integer myIntElementName;
    
        public String getMyStringElementName() {
            return myStringElementName;
        }
    
        public void setMyStringElementName(String value) {
            this.myStringElementName = value;
        }
    
        public Integer getMyIntElementName() {
            return myIntElementName;
        }
    
        public void setMyIntElementName(Integer value) {
            this.myIntElementName = value;
        }
    
    }
    

    更多信息

    【讨论】:

    • 最近有没有人告诉过你你很棒?如果你不介意,还有一个问题。我是否应该始终在 JAXB 类中注释属性而不是关联的 getter/setter 方法?
    • 注释getter(或setter)通常是最安全的做法。例如,如果您对 JAXB 和 JPA 使用相同的模型,那么 JPA 实现会修改字节码以支持调用 getter 时触发的延迟加载。欲了解更多信息,请参阅:blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 2018-04-22
    • 2017-04-03
    • 1970-01-01
    • 2020-08-25
    • 1970-01-01
    相关资源
    最近更新 更多