2012-01-27 86 views
1

使用Smooks(1.4)讀取CSV並將它們轉換爲Person POJO。使用Smooks讀取CSV

的CSV由每行逗號分隔的記錄,每條記錄都有豎線分隔的字段:

史密斯|約翰| 45 |男|約翰尼| JSMITH | JSmizzle,

史密斯|簡| 43 |女| Janey

等。因此,每一行代表一個不同的人來創建。首先,一個POJO:

public class Person 
{ 
    private String lastName; 
    private String firstName; 
    private int age; 
    private boolean isMale; 
    private List<String> aliases; 
} 

我的問題是別名的List。下面是我的XML配置的重要部分:

<reader class="org.milyn.csv.CSVReader"> 
    <param name="fields">lastName,fristName,age,gender,aliases</param> 
    <param name="separator">&#124;</param> 
    <param name="strict">false</param> 
</reader> 

<core:filterSettings type="SAX"/> 

<jb:bean beanId="person" class="net.me.myproject.app.Person" createOnElement="csv-set/csv-record/"> 
    <jb:value property="lastName" data="csv-set/csv-record/lastName"/> 
    <jb:value property="firstName" data="csv-set/csv-record/firstName"/> 
    <jb:value property="isMale" data="csv-set/csv-record/gender"/> 
    <jb:value property="age" data="csv-set/csv-record/age"/> 
    <jb:wiring property="aliases" beanRefId="aliases"/> 
</jb:bean> 

<jb:bean beanId="aliases" class="java.util.ArrayList" createOnElement="???"> 
    <jb:wiring beanRefId="alias"/> 
</jb:bean> 

<jb:bean beanId="alias" class="java.util.String" createOnElement="???"> 
    ??? 
</jb:bean> 

那麼,我窒息是獲得正確的aliases的ArrayList以及每個alias字符串配置createOnElement。預先感謝任何能夠讓我朝正確方向發展的人!

+0

你有過任何控制傳入文件格式?當將媒體資產元數據從XML平面化到管道分隔的文本時,類似「流派」或「演員」的字段有時不得不包含列表,我們遇到了類似的問題。我們用另一個分隔符結束了用這樣的列表分隔元素。科隆在我們的案件中工作得很好 – Olaf 2012-01-30 19:36:12

+0

我喜歡奧拉夫的方法比接受的答案更多。 – Alfabravo 2012-01-31 20:05:48

回答

4

首先,你CSVReader的‘領域’屬性將包含在CSV文件中的所有字段的大雜燴,irregardless其中POJO,列表或類型它們映射回。因此,一些字段將是Person屬性,並且一些字段將是實際屬於單獨的aliases bean的別名,該類型的類型爲java.util.ArrayList<String>

您的工作是告訴Smooks如何將每個字段映射到相應的bean/list/component/type/etc,這意味着告訴它在遇到每個字段時應該如何操作。

Smooks不支持這種「動態」字段綁定,您可以將0+個CSV字段映射回ArrayList,該字段本身將爲空或填充。您必須枚舉CSVReader中的每個字段,這意味着有一個具有固定大小的別名ArrayList

人體工程學,你必須在字段列表決定可以與各個Person相關別名的最大數量,並交代他們:

<reader class="org.milyn.csv.CSVReader"> 
    <param name="fields">lastName,fristName,age,gender,alias1,alias2,alias3</param> 
    <param name="separator">&#124;</param> 
    <param name="strict">false</param> 
</reader> 

這意味着每個CSV記錄必須有一個可信的價值爲你的3個別名。我建議有一個「忽略」值,例如「%%%IGNORE%%%」,以便您的應用邏輯不能刪除包含該值的列表項(在Smooks完成執行轉換後)。

您可能還想查看Smooks的內置$ignore$令牌,該令牌可能已經執行了此操作或類似的操作。

在我們將所有東西都捆綁在一個完整的代碼示例中之前的最後一件事是簡單地接受Smook或者沒有(或者沒有公開記錄)在這種示例中使用List<String>的任何能力的悲傷事實。您必須將您的POJO轉換爲使用List<StringBuffer>List<StringBuilder>作爲別名,以便我們可以提及稱爲setterMethod的Smooks-JavaBean value元素屬性。

現在總共:

<jb:bean beanId="aliases" class="java.util.ArrayList" createOnElement="csv-set/csv-record"> 
    <jb:wiring beanRefId="alias1"/> 
    <jb:wiring beanRefId="alias2"/> 
    <jb:wiring beanRefId="alias3"/> 
</jb:bean> 

<jb:bean beanId="alias1" class="java.util.StringBuffer" createOnElement="csv-set/csv-record/alias1"> 
    <jb:value data="csv-set/csv-record/alias1" setterMethod="append" /> 
</jb:bean> 

<jb:bean beanId="alias2" class="java.util.StringBuffer" createOnElement="csv-set/csv-record/alias2"> 
    <jb:value data="csv-set/csv-record/alias2" setterMethod="append" /> 
</jb:bean> 

<jb:bean beanId="alias3" class="java.util.StringBuffer" createOnElement="csv-set/csv-record/alias3"> 
    <jb:value data="csv-set/csv-record/alias3" setterMethod="append" /> 
</jb:bean> 

所以每次我們開始分析新csv-record時候,我們同時建立person豆(如您最初的代碼示例中完美展現),以及一個aliases豆。然後,在解析這個記錄的過程中,我們會發現Person屬性以及alias1alias3。該aliasN領域得到存入aliases豆,同時其他Person場被存儲到person豆。最後,Smooks的認識到「線」的personaliases豆一起創建一個Java Person對象。

0

好的回覆亞當。

在你到底有沒有提出的名單問題...我還沒有嘗試過,但我不得不盡管以下應該工作...

<jb:bean beanId="aliases" class="java.util.ArrayList" createOnElement="csv-set/csv-record"> 
    <jb:value data="csv-set/csv-record/alias1" decoder="String"/> 
    <jb:value data="csv-set/csv-record/alias2" decoder="String"/> 
    <jb:value data="csv-set/csv-record/alias3" decoder="String"/> 
</jb:bean>