I have struggled for the same issue for a couple of hours..
Finally I found this solution for mapping the right column for POJO and output with header with the opencsv.
Hope this can help you a little bit.
There are 2 points we need to pay extra attention.
1. Must add both of the annotations(e.g. `@CsvBindByPosition(position = 0)` and `@CsvBindByName(column = "var_0")`) on the field in the POJO.
2. Must configure the right mapping strategy and apply it on the instance of `StatefulBeanToCsv`
## Here is the sample code
dependency:
```
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>4.6</version>
</dependency>
```
Class of `CustomMappingStrategy`:
```
import com.opencsv.bean.BeanField;
import com.opencsv.bean.ColumnPositionMappingStrategy;
import com.opencsv.bean.CsvBindByName;
import com.opencsv.exceptions.CsvRequiredFieldEmptyException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
public class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
super.setColumnMapping(new String[ FieldUtils.getAllFields(bean.getClass()).length]);
final int numColumns = findMaxFieldIndex();
if (!isAnnotationDriven() || numColumns == -1) {
return super.generateHeader(bean);
}
String[] header = new String[numColumns + 1];
BeanField<T> beanField;
for (int i = 0; i <= numColumns; i++) {
beanField = findField(i);
String columnHeaderName = extractHeaderName(beanField);
header[i] = columnHeaderName;
}
return header;
}
private String extractHeaderName(final BeanField<T> beanField) {
if (beanField == null || beanField.getField() == null
|| beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class).length == 0) {
return StringUtils.EMPTY;
}
final CsvBindByName bindByNameAnnotation = beanField.getField()
.getDeclaredAnnotationsByType(CsvBindByName.class)[0];
return bindByNameAnnotation.column();
}
}
```
code of the logic to output List<POJO> into a csv:
```
List<POJO> sourceList = new ArrayList<>();
sourceList.add(pojo1);
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File("./test.csv"), false), Charset.forName("UTF-8"));
CustomMappingStrategy<POJO> mappingStrategy = new CustomMappingStrategy<>();
mappingStrategy.setType(POJO.class);
StatefulBeanToCsv<POJO> sbc = new StatefulBeanToCsvBuilder<POJO>(writer)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withMappingStrategy(mappingStrategy)
.build();
sbc.write(sourceList);
writer.flush();
```
Reference:
https://stackoverflow.com/a/58833974/15581209
CustomMappingStrategy for generic class.
```
public class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
super.setColumnMapping(new String[ FieldUtils.getAllFields(bean.getClass()).length]);
final int numColumns = findMaxFieldIndex();
if (!isAnnotationDriven() || numColumns == -1) {
return super.generateHeader(bean);
}
String[] header = new String[numColumns + 1];
BeanField<T> beanField;
for (int i = 0; i <= numColumns; i++) {
beanField = findField(i);
String columnHeaderName = extractHeaderName(beanField);
header[i] = columnHeaderName;
}
return header;
}
private String extractHeaderName(final BeanField<T> beanField) {
if (beanField == null || beanField.getField() == null
|| beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class).length == 0) {
return StringUtils.EMPTY;
}
final CsvBindByName bindByNameAnnotation = beanField.getField()
.getDeclaredAnnotationsByType(CsvBindByName.class)[0];
return bindByNameAnnotation.column();
}
}
```
POJO Class
```
public class Customer{
@CsvBindByPosition(position=1)
@CsvBindByName(column="CUSTOMER", required = true)
private String customer;
}
```
Client Class
```
List<T> data = getEmployeeRecord();
CustomMappingStrategy custom = new CustomMappingStrategy();
custom.setType(Employee.class);
StatefulBeanToCsv<T> writer = new StatefulBeanToCsvBuilder<T>(response.getWriter())
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withSeparator('|')
.withOrderedResults(false)
.withMappingStrategy(custom)
.build();
writer.write(reportData);
```