Search code examples
javacsvparsingunivocity

How to validate CSV headers using Univocity routines?


Im using Univocity CSV parser with routines when I iterate over Java beans. Is there a way to validate CSV header? When I edit the CSV and add invalid header, it just insert into given bean null without any error.

Model class:

public class Customer {

@Format(formats ="yyyy-MM-dd")
@Parsed(field="C_DAY")
private Date day;

@Parsed(field="C_ID")
private Long id;

@Parsed(field="C_TYPE")
private String type;

@Format(formats ="yyyy-MM-dd")
@Parsed(field="C_ORIGIN_DATE")
private Date originDate;

@Format(formats ="yyyy-MM-dd")
@Parsed(field="C_REL_DATE")
private Date relDate;

@Parsed(field="C_LEGAL_ID")
private String legalId;

@Parsed(field="C_NAME")
private String name;}

Parser:

    @Autowired
private CustomerDAO dao;

public void parse(File file) throws IOException, SQLException, CustomerValidationException, ParseException {
    CsvParserSettings parserSettings = new CsvParserSettings();
    parserSettings.getFormat().setLineSeparator("\n");
    parserSettings.setHeaderExtractionEnabled(false);
    CsvRoutines routines = new CsvRoutines(parserSettings);
    List<Customer> customers = new ArrayList<>();
    java.util.Date stamp = getTimestamp(file);
    dao.checkTimestampDate(stamp);


    for (Customer customer : routines.iterate(Customer.class, file, "UTF-8")) {
        validateFileDateWithFileName(stamp, customer.getDay());
        validateCustomer(customer);
        customers.add(customer);
    }
    dao.save(customers);
}

Solution

  • Author of the library here. The BeanListProcessor has a strictHeaderValidationEnabled property you can set to true to ensure all headers in your class exist in the input.

    You just can't use the CsvRoutines in that case as that class implements convenience methods that use their own internal row processors, so yours will be ignored. Try this code:

        CsvParserSettings parserSettings = new CsvParserSettings();
        parserSettings.getFormat().setLineSeparator("\n");
    
        final List<Customer> customers = new ArrayList<>();
        final java.util.Date stamp = getTimestamp(file);
        dao.checkTimestampDate(stamp);
    
        parserSettings.setProcessor(new BeanProcessor<Customer>() {
            @Override
            public void beanProcessed(Customer customer, ParsingContext context) {
                validateFileDateWithFileName(stamp, customer.getDay());
                validateCustomer(customer);
                customers.add(customer);
            }
        });
    
        new CsvParser(parserSettings).parse(file, "UTF-8");
    
        dao.save(customers);
    

    Hope this helps.