2

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

Karan
  • 752
  • 2
  • 13
  • 34

1 Answers1

7

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();


aksappy
  • 3,400
  • 3
  • 23
  • 49
  • 1
    Thanks, this is exactly what I was looking for. – Karan Jul 26 '21 at 15:01
  • @Karan - another way to say "thanks" is described [here](https://stackoverflow.com/help/someone-answers). (But as it notes, accepting answers and voting are always optional.) – andrewJames Jul 26 '21 at 15:46
  • Is there a way that to use @PreAssignmentValidator with profiles? I tried something like this, didn't work(not adding symbol before annotation for restriction on formatting rules): PreAssignmentValidator CsvBindByNames({ CsvBindByName, CsvBindByName(column = "first name", profiles = "customer 1") }) private String name – Abhinash Jha Apr 04 '23 at 21:15