2012-07-04 26 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,非常好的答案,非常感謝您的時間:-) –