uniVocity - преобразование в список по позиции

Я пытаюсь создать список из конкретных позиций в файле CSV, вместо скобок.

class Person {//
@Parsed
private String name;
@??
private Address address;
@Convert(conversionClass = Emails2.class, args = { "," , "5,6" })
@Parsed
private List<String> emails;
}

формат CSV:

name,email1,email2,email3,street,number,neighborhood
Maria,ma@gmail.com,ma@hotmail.com,,Regent Street,12,downtown
Ana,ana@gmail.com,a@hotmail.com,,Bird Street,,east side

Мне нужно прочитать файл CSV и создать список электронных писем и объект адреса. Я пытался использовать @Convert,

public class Emails2 implements Conversion<String, Set<String>> {

    private final String separator;
    private final Set<String> positions;

    public Emails2(String... args) {
        String separator = ",";
        Set<String> positions = null;

        if (args.length == 1) {
            separator = args[0];
        }

        if (args.length == 2) {
            positions = new HashSet<String>();
            String[] posi = args[1].split(",");
            for (String string : posi) {
                positions.add(string);
            }
        }
        this.separator = separator;
        this.positions = positions;
    }

    public Emails2(String separator, Set<String> positions) {
        this.separator = separator;
        this.positions = positions;
    }
//this method is not called, I don't know why
    public Set<String> execute(String input) { //I would like add the list and Address object inside this method to get it done in beanProcessed(...)
        if (input == null) {
            return Collections.emptySet();
        }

        Set<String> out = new TreeSet<String>();
        for (String token : input.split(separator)) {
            for (String word : token.trim().split("\\s")) {
                out.add(word.trim());
            }
        }
        return out;
    }

    public String revert(Set<String> input) {
        return revert(input);
    }

}

Как у меня дела

    public static void main(String[] args) {

            BeanProcessor<Person> rowProcessor = new BeanProcessor<Person>(Person.class) {
                @Override
                public void beanProcessed(Person c, ParsingContext context) {
                    System.out.println(c.getName());

                    String[] positions = context.currentParsedContent().split(","); 
                    System.out.println(positions[5]);
//I'm using fixed position here, I'd like get the position from @Convert or another way by configuration
                    System.out.println(positions[6]);
                    List<String> list = new ArrayList<>();
                    list.add(positions[5]);
                    list.add(positions[6]);
                    c.setEmails(list);
                }

            };

            CsvParserSettings parserSettings = new CsvParserSettings();
            parserSettings.setRowProcessor(rowProcessor);
            parserSettings.setHeaderExtractionEnabled(true);
            CsvParser parser2 = new CsvParser(parserSettings);
            parser2.parse(getReader("/var/lib/cob/test2.csv"));

        }

2 ответа

Я достиг того, чего хочу, по-другому, не так, как хотелось бы, но это сработало. Я использовал MultiBeanProcessor и создал фиктивные классы (моему боссу не понравится) для представления моих позиций в CSV.

Мой настоящий CSV имеет заголовки, такие как:

EMAIL1,email2,email3,dddcel1,dddcel2,dddcel3,dddcel4,dddtel1,dddtel2,dddtel3, ПгвЬЫат, документ,v_atu,ofe_cc,ignore1, банк, агентство, ignore2, INVOICENUMBER, contactPhone, адрес, район, почтовый индекс, город, штат

    class Email{
    @Parsed 
    private String email1;
    @Parsed 
    private String email2;
     @Parsed
    private String email3;
    }

class Mobile{
    @Parsed
    private String dddcel1;
    @Parsed
    private String dddcel2;
    @Parsed
    private String dddcel3;
    @Parsed
    private String dddcel4;
}

И MultiBeanProcessor

 MultiBeanProcessor processor = new MultiBeanProcessor(Customer.class, Address.class, Email.class, Mobile.class, Phone.class) {
            private Customer customer;
            private Address address;
            private Email email;
            private Mobile mobile;
            private Phone phone;

            @Override
            public void beanProcessed(Class<?> beanType, Object beanInstance, ParsingContext context) {

                if (beanType == Customer.class) {
                    customer = (Customer) beanInstance;
                    customer.set_id(UUID.randomUUID().toString());
                    customer.setStatus(CustomerStatusType.PENDING);
                    customer.setDiscountValue(customer.getInvoiceValue() - customer.getTotalValue());
                    customer.setToken(UUID.randomUUID().toString());
                    try {
                        customer.setCreated(new java.text.SimpleDateFormat("yyyy-MM-dd")
                                .parse((new java.text.SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date()))));
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }

                    customer.setDomain("???????????");
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("banco", customer.getBank());
                    map.put("agencia", customer.getAgency());
                    customer.setInvoiceDetail(map);

                }

                if (beanType == Address.class) {
                    address = (Address) beanInstance;
                    customer.setAddress(address);
                }

                if (beanType == Email.class) {
                    email = (Email) beanInstance;
                    customer.setEmails(Arrays.asList(email.getEmail1(), email.getEmail2(), email.getEmail3()));
                }

                if (beanType == Mobile.class) {
                    mobile = (Mobile) beanInstance;
                    customer.setMobiles(Arrays.asList(mobile.getDddcel1(), mobile.getDddcel2(), mobile.getDddcel3(), mobile.getDddcel4()));

                }

                if (beanType == Phone.class) {
                    phone = (Phone) beanInstance;
                    customer.setPhones(Arrays.asList(phone.getDddtel1(), phone.getDddtel2(), phone.getDddtel3()));
                }

                if (customer != null && address != null && email != null && mobile != null & phone != null) {
                    System.out.println(customer);//save customer object
                    customer = null;
                    address = null;
                    email = null;
                    phone = null;
                    mobile = null;
                }

            }
        };

Я еще тестирую, надеюсь, что он работает на 500 тыс. Строк:)

Вы пытаетесь присвоить значения нескольким столбцам (email1, email2, email3) в один атрибут (Person.emails) через пользовательское преобразование, но это не поддерживается, поскольку преобразование предназначено для одного поля (или столбца ввода) вместо всей строки.

Кроме того, execute метод в вашем пользовательском преобразовании не будет вызван, потому что нет emails заголовок на входе. Когда вы аннотируете атрибут с @Parsed В аннотации без указания имени заголовка будет использовано само имя атрибута. Если вы переименуете атрибут из emails в email1 вы увидите, что будет вызван ваш класс преобразования, или если вы просто предоставите имя поля в аннотации, например:

@Parsed(field = "email1")
private List<String> emails;

Это также будет называться.

Я вижу, что вы пытаетесь сделать здесь, и открыл эту проблему, чтобы обеспечить лучшую поддержку для такого рода требований.

Надеюсь это поможет.

Другие вопросы по тегам