2012-07-04 23 views
0

我对JAXB并不是很熟悉,但这是我拥有的上下文,请阅读所有需要理解的内容。无法在JAXB生成的模型中调用空值的“get”

我做以下获得使用JAXB从这个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> 
         <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 from PostalAddress我使用此代码:

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

但我不喜欢做的if语句我的XML的每个实体。正如我所说的,我想在不修改代码的情况下自动执行某些操作,并且我不知道是否有一些JAXB配置或需要执行的操作。

在此先感谢。

+0

如果你正在提取有限的信息,并且正在创建对象,其中大部分你不会使用或需要,那么也许你应该考虑通过使用XPath或类似的东西来简化事情。 –

+0

@HovercraftFullOfEels不是一个有限的信息量,我正在提取一个大的值列表,我只是把我的问题的一个例子理解为:-) –

+0

由于没有“JAXB故障”,所以您的问题的标题已更改。 –

回答

1

JAXB (JSR-222)是将对象转换为/从XML转换为Java的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值,但out输出包含一个额外的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 - 检查值不为空调用得到它

此选项是更多一点的工作之前,但最终将使您的应用程序更易于维护。

+0

选项3是我作为我的“解决方案”所做的选择,但我正在处理大量的值,如果实体为空或者没有,我会讨厌做大量if语句。不幸的是,我想我会选择选项1或2,非常好的答案,非常感谢您的时间:-) –