繁体   English   中英

无法在JAXB生成的模型的空值上调用“获取”

[英]Can't call “get” on null value in JAXB generated model

我对JAXB不太熟悉,但这是我所拥有的上下文,请阅读所有内容以了解。

1.我正在执行以下操作,以从此XML使用JAXB获取值...

XML文档片段(原始):

 <Request deploymentMode="production">
        <OrderRequest>
             <OrderRequestHeader orderID="12345" orderDate="2012-07-04" type="new">
                 <Total>
                     <Money currency="USD">200.0</Money>
                 </Total>
                 <ShipTo>
                     <Address>
                         <Name xml:lang="">Test</Name>
                         <PostalAddress name="default">
                             <DeliverTo/>
                             <Street>Value 1</Street>
                             <City>Value 2</City>
                             <State>Value 3</State>
                             <PostalCode>302010</PostalCode>
                             <Country isoCountryCode="US">USA</Country>
                         </PostalAddress>
                     </Address>
                 </ShipTo>

因此,我想要的值是PostalAddressState ,我使用以下代码:

String state = xml.getRequest().getOrderRequest().getOrderRequestHeader().getShipTo().getAddress().getPostalAddress().getState();
//This will return "Value 3"

而且一切正常。

2.问题从这一点开始,我将执行与上面相同的操作,但是现在使用此XML ...

XML文档片段(其他):

 <Request deploymentMode="production">
        <OrderRequest>
             <OrderRequestHeader orderID="12345" orderDate="2012-07-04" type="new">
                 <Total>
                     <Money currency="USD">200.0</Money>
                 </Total>
                 <ShipTo>
                     <Address>
                         <Name xml:lang="">Test</Name>
                     </Address>
                 </ShipTo>

好吧,我知道该值不存在,但是我不想对我的代码进行任何更改并且仍在使用它:

String state = xml.getRequest().getOrderRequest().getOrderRequestHeader().getShipTo().getAddress().getPostalAddress().getState();

上面的代码将产生NullPointerException并停止该过程。 我不需要停止进程,因为这不是我从XML提取的唯一值(这只是我正在处理的示例)。 因此,如果找不到该值,那么我希望state变量自动为null

问:是否有一种方法不产生异常,如果找不到值,使我的字符串变量state null


PS。 一个可能的解决方案可能是做这样的事情:

//Fill the entity
PostalAddressType p = xml.getRequest().getOrderRequest().getOrderRequestHeader().getShipTo().getAddress().getPostalAddress();
//Variable for state
String state = null;
//Evaluate if it is null or not
if(p != null)
    //Capture the value if not null
    state = p.getState();

但是我不喜欢为我的XML的每个实体都做一个if语句。 就像我说的那样,我希望无需修改代码就可以实现自动化,并且我不知道是否需要一些JAXB配置或为此执行某些操作。

提前致谢。

JAXB(JSR-222)是用于将对象与XML相互转换的Java标准。 有多种开源实现。 JAXB使用的对象是POJO(普通的Java对象)。 这些类中没有任何XML逻辑。 由于JAXB旨在与现有类一起使用,因此可能存在一些逻辑可以支持您的用例。 以下是几个选项。

选项#1-延迟加载PostalAddress属性(不推荐)

地址

如果属性为null则可以向getPostalAddress()方法添加逻辑以实例化PostalAddress的实例。

package forum11333165;

import javax.xml.bind.annotation.*;

@XmlRootElement(name="Address")
public class Address {

    private String name;
    private PostalAddress postalAddress;

    @XmlElement(name="Name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @XmlElement(name="PostalAddress")
    public PostalAddress getPostalAddress() {
        if(null == postalAddress) {
            postalAddress = new PostalAddress();
        }
        return postalAddress;
    }

    public void setPostalAddress(PostalAddress postalAddress) {
        this.postalAddress = postalAddress;
    }

}

邮寄地址

package forum11333165;

import javax.xml.bind.annotation.XmlElement;

public class PostalAddress {

    private String state;

    @XmlElement(name="State")
    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

}

演示版

下面的演示代码演示了您将能够

package forum11333165;

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

public class Demo {

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

        StringReader xml = new StringReader("<Address><Name>Test</Name></Address>");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Address address = (Address) unmarshaller.unmarshal(xml);

        System.out.println(address.getPostalAddress().getState());

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

}

输出量

以下是运行演示代码的输出。 如您所见,我们得到了我们一直在寻找的null值,但是输出包含一个额外的PostalAddress方法。

null
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Address>
    <Name>Test</Name>
    <PostalAddress/>
</Address>

选项#2-如果属性为Null,则返回一个新实例(不推荐)

地址

package forum11333165;

import javax.xml.bind.annotation.*;

@XmlRootElement(name="Address")
@XmlAccessorType(XmlAccessType.FIELD)
public class Address {

    @XmlElement(name="Name")
    private String name;

    @XmlElement(name="PostalAddress")
    private PostalAddress postalAddress;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public PostalAddress getPostalAddress() {
        if(null == postalAddress) {
            return new PostalAddress();
        }
        return postalAddress;
    }

    public void setPostalAddress(PostalAddress postalAddress) {
        this.postalAddress = postalAddress;
    }

}

输出量

我们可以使用上一个选项中的相同演示代码来产生新的输出。 该get仍然有效,并且我们没有获得额外的PostalAddress方法。 不利的一面是我们认为未设置的状态。

null
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Address>
    <Name>Test</Name>
</Address>  

选项#3-调用Get On之前检查值不为空

这个选项还有点工作,但是最终将使您的应用程序更易于维护。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM