1

使用 Smooks ( 1.4) 读取 CSV 并将其转换为PersonPOJO。

CSV 由每行以逗号分隔的记录组成,每条记录都有用竖线分隔的字段:

史密斯|约翰|45|男|约翰尼|JSmith|JSmizzle,

史密斯|简|43|女|简

等等。因此,每条线代表一个不同的人来创建。首先,一个 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>

所以我窒息的地方是createOnElement正确配置aliasesArrayList 以及每个alias字符串。在此先感谢任何可以将我推向正确方向的人!

4

2 回答 2

4

First of all, your CSVReader's "fields" attribute will be a hodge-podge of all fields contained inside the CSV file, irregardless of which POJO, list or type they map back to. Thus, some fields will be Person properties, and some fields will be aliases that actually belong to the separate aliases bean, which is of type java.util.ArrayList<String>.

Your job is to tell Smooks how to map each field to the respective bean/list/component/type/etc, which means telling it what to do when it encounters each field.

Smooks does not support this sort of "dynamic" field binding, where you can have 0+ CSV fields map back to an ArrayList, that itself will either be empty or populated. You must enumerate each field in the CSVReader, which means having an ArrayList of aliases that has a fixed size.

Ergo, you must decide on a maximum number of aliases that can be associated with each Person, and account for them in the fields list:

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

This means that each CSV record must have a credible value for your 3 aliases. I would recommend having an "ignore" value, such as "%%%IGNORE%%%" so that your app logic can no to remove an list items that contain that value (after Smooks has finished performing the transformation that is).

You might also want to check out Smooks's built-in $ignore$ token, which might already do this or something like it.

The last piece before we can tie everything together in a complete code example is to simply accept the sad fact that Smooks either does not (or does not publicly document) any ability to use List<String> in this kind of example. You must convert your POJO to use either to a List<StringBuffer> or a List<StringBuilder> for aliases, so that we may take advntage of a Smooks-JavaBean value element attribute called setterMethod.

Altogether now:

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

So every time we start parsing a new csv-record, we create both a person bean (as your initial code example shows perfectly) as well as an aliases bean. Then, over the course of parsing this record, we will find Person properties as well as alias1 through alias3. The aliasN fields get stored into the aliases bean, meanwhile the other Person field gets stored into the person bean. Finally, Smooks knows to "wire" the person and aliases beans together to create a Java Person object.

于 2012-01-30T20:04:26.440 回答
0

很好的回答亚当。

关于你最后提出的 List 问题......我没有尝试过,但我认为以下应该可以工作......

<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>
于 2012-02-02T12:43:31.923 回答