n2ad
n2ad

Reputation: 323

Write csv file with pojo containing nested collections

I need to export a pojo to csv with jackson lib. My pojo class contains nested objects (collections). I would like to export the nested collection as a column.

 public class PojoToCsv {
    private String label;
    private Set<String> names;
    @JsonUnwrapped
    private List<Address> addresses;

    public PojoToCsv() {
    }

    
    public PojoToCsv(String label, Set<String> names, List<Address> addresses) {
        this.label = label;
        this.names = names;
        this.addresses = addresses;
    }
    //Setters & Getters
public class Address {
    private String zipCode;
    private String mail;
    private int vatNumber;

For example for this set of data :

Address address1 = new Address("label1","name1",1);
        Address address2 = new Address("label2","name2",2);
        Address address3 = new Address("label3","name3",3);
        Address address4 = new Address("label4","name4",4);

        PojoToCsv pojoToCsv1 = new PojoToCsv("value1", Stream.of("baba","bobo").collect(Collectors.toSet()), Arrays.asList(address1,address2));
        PojoToCsv pojoToCsv2 = new PojoToCsv("value2", Stream.of("tata","toto").collect(Collectors.toSet()), Arrays.asList(address3,address4));

The csv file should be like this:

label,names,addresses
"value1",["baba","bobo"],[{"zipCode":"label1","mail":"name1","vatNumber":1},{"zipCode":"label2","mail":"name2","vatNumber":2}]
"value2",["tata","toto"],[{"zipCode":"label3","mail":"name3","vatNumber":3},{"zipCode":"label4","mail":"name4","vatNumber":4}]

Here is my actuel code :

        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.convertValue(generatePojoList(), JsonNode.class);

        CsvSchema.Builder csvSchemaBuilder = CsvSchema.builder();
        JsonNode firstNode = node.elements().next();
        firstNode.fieldNames().forEachRemaining(name -> {csvSchemaBuilder.addColumn(name);});
        CsvSchema csvSchema = csvSchemaBuilder.build().withHeader();

        CsvMapper csvMapper = new CsvMapper();
        csvMapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);

        csvMapper.writerFor(JsonNode.class)
                .with(csvSchema)
                .writeValue(new File("src/main/resources/export.csv"), node);

I'm still getting an exception CsvMappingException: CSV generator does not support Object values for properties (nested Objects)

Upvotes: 2

Views: 2896

Answers (1)

n2ad
n2ad

Reputation: 323

Here is a solution with Apache Commons CSV lib:

ObjectMapper objectMapper = new ObjectMapper();
        CSVPrinter csvPrinter = null;
        FileWriter fileWriter = null;
        CSVFormat csvFormat = CSVFormat.DEFAULT.withRecordSeparator("\n");
        final Object[] CSV_FILE_HEADERS = {"label", "names", "addresses"};
        try {
            fileWriter = new FileWriter("export.csv");
            csvPrinter = new CSVPrinter(fileWriter, csvFormat);
            csvPrinter.printRecord(CSV_FILE_HEADERS);
            for (PojoToCsv csvObject : generatePojoList()) {
                List<String> data = Arrays.asList(
                        csvObject.getLabel(),
                        String.valueOf(objectMapper.writeValueAsString(csvObject.getNames())),
                        String.valueOf(objectMapper.writeValueAsString(csvObject.getAddresses()))
                );
                csvPrinter.printRecord(data);
            }
        } catch (Exception e) {
            System.out.println("CSV writing error");
            e.printStackTrace();
        } finally {
            try {
                fileWriter.flush();
                fileWriter.close();
                csvPrinter.close();
            } catch (IOException e) {
                System.out.println("closing error");
                e.printStackTrace();
            }
        }

Where generatePojoList() is a method providing the pojo collection to export.

Upvotes: 2

Related Questions