How to dynamically assign headers to a csv file using CsvMapper in Java

Wil Ferraciolli picture Wil Ferraciolli · Jun 27, 2017 · Viewed 11.1k times · Source

Can anyone help please? I am stuck on reading a csv file and serializing it onto a POJO. I am using CsvMapper from jackson library. The reading and serialization part are done and works fine-ish. The issue is when the user moves the headers/columns around causing the serialization to make some alphabetical assumption that the values on the CSV file are also alphabetically.
Eg (File below has headers on the first row and the second row has person details values) personNameHeader,personAgeHeader Wiliam,32

Now my POJO is as follow

@JsonIgnoreProperties(ignoreUnknown = true)
// @JsonPropertyOrder(value = {"personNameHeader", "personAgeHeader" })
public class PersonDetailsCSVTemplate  {

@JsonProperty("personNameHeader")
private String name;

@JsonProperty("personAgeHeader")
private String age;

//Public constructor and getters and setters...

This is the code to read the values from the CSV and map onto the class

import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
...

    CsvMapper csvMapper = new CsvMapper();    
    CsvSchema schema = csvMapper.typedSchemaFor(PersonDetailsCSVTemplate.class).withHeader();
          MappingIterator<PersonDetailsCSVTemplate  > dataIterator = csvMapper.readerFor(PersonDetailsCSVTemplate.class).with(schema)
            .readValues(data);

     while (dataIterator.hasNextValue()) {
        PersonDetailsCSVTemplate dataCSV = dataIterator.nextValue();
}

After the serialization it can be seen that CsvMapper mapped the following: PersonDetailsCSVTemplate.name = "32" andPersonDetailsCSVTemplate.age = "Wiliam"

By annotating the class with @JsonPropertyOrder(value = {"personNameHeader", "personAgeHeader" }) forces the CSV to be always name column followed by age column which isnt ideal.

Can anyone suggest anything that they think will work? Regards

Answer

Nathan picture Nathan · Dec 6, 2018

Since Jackson 2.7, you can use withColumnReordering(true) instead of sortedBy()

CsvSchema schema = csvMapper
    .typedSchemaFor(PersonDetailsCSVTemplate.class)
    .withHeader()
    .withColumnReordering(true);