2012-01-27 2 views
1

Использование Smooks (1.4) для чтения CSV и преобразования их в Person POJO.Чтение CSV с Smooks

CSV-состоит из разделенных запятыми записей в каждой строке, и каждая запись имеет трубные разделителями полей:

Смит | Джон | 45 | мужчина | Johnny | JSmith | JSmizzle,

Смит | Jane | 43 | female | 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> 

Так где я задыхался в получении createOnElement правильно настроить для aliases ArrayList, а также каждого alias String. Заранее благодарю любого, кто может подтолкнуть меня в правильном направлении!

+0

У вас есть контроль над формат входящего файла? У нас была аналогичная проблема при сглаживании метаданных медиа-активов из XML в текст, разделенный на трубы, где иногда такие поля, как «жанр» или «актер», должны содержать списки. Мы разделили элементы с таким списком другим разделителем. Колон прекрасно работал в нашем случае. – Olaf

+0

Мне нравится подход Олафа больше, чем принятый ответ. – Alfabravo

ответ

4

Прежде всего, ваши CSVReader «ы„поля“атрибут будет мешанина из всех полей, содержащихся в файле CSV, который Вне зависимости от POJO, список или они типа карты обратно. Таким образом, некоторые поля будут иметь свойства Person, а некоторые поля будут алиасами, которые фактически принадлежат отдельному компоненту aliases, который имеет тип java.util.ArrayList<String>.

Ваша задача - показать Smooks, как сопоставить каждое поле с соответствующим компонентом/списком/компонентом/типом/и т. Д., Что означает говорить ему, что делать, когда он сталкивается с каждым полем.

Smooks не поддерживает подобную «динамическую» привязку поля, где вы можете иметь 0 + поля CSV, чтобы вернуться к ArrayList, что само по себе будет либо пустым, либо заполненным. Вы должны перечислить каждое поле в CSVReader, что означает наличие ArrayList псевдонимов с фиксированным размером.

Ergo, вы должны принять решение о максимальном количестве псевдонимов, которые могут быть связаны с каждым 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's $ignore$, который может уже сделать это или что-то в этом роде.

Последний фрагмент, прежде чем мы можем связать все вместе в полном примере кода, - это просто принять печальный факт, что Smooks либо не (или не публично документирует) любую возможность использовать List<String> в этом примере. Вы должны преобразовать свой POJO, чтобы использовать либо для List<StringBuffer>, либо для List<StringBuilder> для псевдонимов, чтобы мы могли использовать атрибут элемента Smooks-JavaBean value с именем setterMethod.

В целом в настоящее время:

<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, а также alias1 до alias3. Поля aliasN сохраняются в bean-компоненте aliases, а другое поле Person сохраняется в bean-компоненте person. Наконец, Smooks знает, как «пронести» person и aliases бобы вместе, чтобы создать объект Java Person.

0

Nice reply Adam.

По вопросу списка вы подняли в конце концов там ... Я не пробовал, но я бы, хотя должно работать ...

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