Search code examples
javaspring-bootopencsv

OpenCSV, how to write into csv with custom processing?


I am trying to write List of POJO objects into a csv. I use opencsv and the code is very minimal:

 StatefulBeanToCsv sbc = new StatefulBeanToCsvBuilder(writer)
                    .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
                    .build();

I use Custom converters while reading, can I do something similar for write also? For e.g.:

  1. if field is of type List, it gets written as "[a,b]". But I would like to do something like this: "a,b".
  2. A field is of type LocalDataTime, I would like to write it in the format "MM/dd/yyyy" and discard time completely in the output csv.

I want output to be something like this:

date of issue,items
"02/22/2020","a,b"

Instead of:

date of issue,items
"2020-02-22T00:00","[a,b]"

Thank you so much, appreciate any help :)


Solution

  • You can use the annotations @CsvDate for set custom date format and @CsvBindAndSplitByName for the conversion of the list to string. Please find below example:

    import static java.time.temporal.ChronoUnit.MONTHS;
    
    import com.opencsv.CSVWriter;
    import com.opencsv.bean.CsvBindAndSplitByName;
    import com.opencsv.bean.CsvBindByName;
    import com.opencsv.bean.CsvDate;
    import com.opencsv.bean.StatefulBeanToCsv;
    import com.opencsv.bean.StatefulBeanToCsvBuilder;
    
    
    import java.io.FileWriter;
    import java.io.Writer;
    import java.time.LocalDateTime;
    import java.util.List;
    
    public class Main {
    
        public static void main(String[] args) throws Exception {
    
            Writer writer = new FileWriter("example.csv");
    
            StatefulBeanToCsv<Item> sbc = new StatefulBeanToCsvBuilder<Item>(writer)
                    .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
                    .build();
    
            List<Item> items = List.of(
                    new Item(LocalDateTime.now().minus(4, MONTHS), List.of("1", "s")),
                    new Item(LocalDateTime.now().minus(1, MONTHS), List.of("1", "d")),
                    new Item(LocalDateTime.now().minus(3, MONTHS), List.of("1", "2", "3"))
            );
            sbc.write(items);
    
            writer.close();
    
    
        }
    
        public static class Item {
    
            @CsvBindByName(column = "date")
            @CsvDate(value = "yyyy-MM-dd'T'hh:mm")
            private LocalDateTime date;
    
            @CsvBindAndSplitByName(column = "list", elementType = String.class, writeDelimiter = ",")
            private List<String> array;
    
            Item(LocalDateTime date, List<String> array) {
                this.date = date;
                this.array = array;
            }
    
            public LocalDateTime getDate() {
                return date;
            }
    
            public void setDate(LocalDateTime date) {
                this.date = date;
            }
    
            public List<String> getArray() {
                return array;
            }
    
            public void setArray(List<String> array) {
                this.array = array;
            }
        }
    }
    

    The output of example.csv:

    "DATE","LIST"
    "2020-03-10T02:37","1,s"
    "2020-06-10T02:37","1,d"
    "2020-04-10T02:37","1,2,3"