Search code examples
javaenumsopencsv

Opencsv convertion bean enums to csv


I would like to write a csv file from a bean with enums. My bean contains:

@NotNull(message = "userRole should not be blank")
private UserRole userRole;

UserRole class:

@Getter
@RequiredArgsConstructor
public enum UserRole {
    STUDENT("student"),
    TEACHER("teacher");

    private final String value;
}

Building csv file looks like that:

private <T extends CsvBean> String writeCsvFromBean(Path ddir, String fileName, List<T> obj) throws IOException, CsvDataTypeMismatchException, CsvRequiredFieldEmptyException {
    String filePath = ddir.resolve(fileName).toString();
    try (Writer writer  = new FileWriter(filePath)) {
        StatefulBeanToCsv<T> sbc = new StatefulBeanToCsvBuilder<T>(writer)
        .withSeparator(ICSVWriter.DEFAULT_SEPARATOR)
        .build();

        sbc.write(obj);
    }
    return filePath;
}

In the resulted csv file I can see the enum values listed as STUDENT/TEACHER (capital letters) instead of enum's valueOf results student/teacher. How to force opencsv to generate csv based on enum valueOf?

BR


Solution

  • By default enum conversion is using name() of the enum, referring to ConverterEnum. You may override this conversion using CsvCustomBindByName and create a custom converter.

    import com.opencsv.bean.CsvCustomBindByName;
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class CsvBean {
        @CsvCustomBindByName(converter = UserRoleConverter.class)
        private UserRole userRole;
    }
    
    import com.opencsv.bean.AbstractBeanField;
    
    import java.util.Arrays;
    
    public class UserRoleConverter extends AbstractBeanField<UserRole, String> {
        // for reading back from csv to bean
        @Override
        protected Object convert(String value) {
            return Arrays.stream(UserRole.values())
                    .filter(userRole -> userRole.getValue().equals(value))
                    .findFirst().orElse(null);
        }
    
        @Override
        protected String convertToWrite(Object value) {
            if (value == null) {
                return "";
            }
            return ((UserRole) value).getValue();
        }
    }