Search code examples
javaopencsv

@CsvBindByName - Binding column with alternate column name


I have two csv sources to read data from. Both of the csv files provide the same data but with different name or column location. Is there a way to add @CsvBindByByName with "OR". For example, the headers of two files are as follows

CSV 1 - RollNo, StudentName, Class, Age, PrimaryLanguage, ProjectName

CSV 2 - Name, Class, PrimLang, EnrollmentNumber, Age, Project, AttendancePercentage

And I have to read both of the csv file information in same POJO.

public class StudentInfo{
@CsvBindByName(column = "RollNo")
private String rollNo;

@CsvBindByName(column = "StudentName")
private String studentName;

@CsvBindByName(column = "PrimaryLanguage")
private String primaryLanguage;

@CsvBindByName(column = "Class")
private String class;

@CsvBindByName(column = "ProjectName")
private String projectName;

@CsvBindByName(column = "Age")
private String age;

//getters and setters
}  

Or is there an alternate way to achieve this. My code is working fine if I take only one csv header format. Thanks


Solution

  • Profiles in opencsv solves this problem, but it is only available from 5.4.

    See documentation on Profiles

    Below is a code snippet from the official documentation.

    public class Person {
      @CsvBindByNames({
        @CsvBindByName(column = "last name"),
        @CsvBindByName(profiles = {"customer 2", "customer 5"})
      })
      private String surname;
    
      @CsvBindByNames({
        @CsvBindByName,
        @CsvBindByName(column = "first name", profiles = "customer 1"),
        @CsvBindByName(column = "given name", profiles = "customer 2")
      })
      private String name;
    
      @CsvIgnore(profiles = "customer 2")
      @CsvBindByName(column = "middle initial")
      private char initial;
    
      @CsvBindByName(column = "salary", profiles = "customer 1")
      @CsvBindByName(column = "annual salary", profiles = "customer 2")
      @CsvNumber(value = "#0.00", profiles = "customer 1")
      @CsvNumber(value = "0.0#E0", profiles = "customer 2")
      private float salaryInUSD;
    
      @CsvBindByName(column = "height")
      @CsvNumbers({
        @CsvNumber("000"),
        @CsvNumber(value = "000cm", profiles = "customer 2")
      })
      private int heightInCentimeters
    
      // Accessor methods go here.
    }
    
    
    // Now, the profile can be used in the builder parse, see below.
    
    List<Person> beans = new CsvToBeanBuilder<Person>(inputfile)
      .withProfile("customer 1")
      .withType(Person.class)
      .build()
      .parse();