在JAXB生成的模型中无法对null值调用“get”

时间:2012-07-04 17:11:01

标签: java xml jaxb xml-parsing nullpointerexception

我对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>

所以,我想要的值是来自State的{​​{1}},我使用此代码:

PostalAddress

一切都很好。

2. 问题从这一点开始,我会像上面一样做,但现在使用这个XML ......

XML文档摘要(其他):

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

嗯,我知道该值不存在,但我不想对我的代码进行任何更改,仍然使用它:

 <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(); 并停止该过程。我需要的是不要停止进程,因为这不是我从XML中提取的唯一值(这只是我正在处理的一个例子)。因此,如果无法找到该值,那么我希望我的NullPointerException变量自动为state

问:如果无法找到值,是否有办法不生成和异常,并使我的字符串变量null只是state?< / em>


PS。可能的解决方案可能是这样做:

null

但我不想为我的XML的每个实体制作一个//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(); 语句。正如我所说的,我想要一些自动化的东西而不修改代码,我不知道是否有一些JAXB配置或者为此做些什么。

提前致谢。

1 个答案:

答案 0 :(得分:1)

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

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

地址

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

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

}

的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 - 如果属性为空则返回新实例(不推荐)

地址

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 - 在调用之前检查值是否为空

这个选项稍微有些工作,但最终会使您的应用程序更容易维护。