Search code examples
javacsvopencsv

OpenCSV flat to hierarchy structure data parsing


I need advice on the issue which I am facing while parsing CSV data in java.

I have a CSV file with data in below format

name, gender, address_first_line, address_second_line, city, number 
me, Male, anonymous, random, Auckland, 6545
other, Female, random, anon, Auckland, 6688

I want to parse the CSV file using the openCSV library in below Object Model. I am aware of parsing single class but facing issues while parsing data when multiple classes are involved. Please suggest if there is any other library available which can help me to get the desired result.

Class User {
    String name;
    String gender;
    Address address;
    long number;
}

Class Address {
   String firstLine;
   String secondLine;
}

Solution

  • univocity-parsers has a @Nested annotation you can use:

    Try this:

    public static class User {
        @Parsed
        String name;
        @Parsed
        String gender;
        @Nested
        Address address;
        @Parsed
        long number;
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", gender='" + gender + '\'' +
                    ", address=" + address +
                    ", number=" + number +
                    '}';
        }
    }
    
    public static  class Address {
        @Parsed(field = "address_first_line")
        String firstLine;
        @Parsed(field = "address_second_line")
        String secondLine;
    
        @Override
        public String toString() {
            return "Address{" +
                    "firstLine='" + firstLine + '\'' +
                    ", secondLine='" + secondLine + '\'' +
                    '}';
        }
    }
    
    public static void main(String ... args){
        StringReader input = new StringReader(
                "name,gender,address_first_line,address_second_line, city,number\n" +
                "John,M,Somewhere,Else,City,1");
    
    
        for(User user : new CsvRoutines().iterate(User.class, input)){
            System.out.println(user.toString());
        }
    
    }
    

    Output:

    User{name='John', gender='M', address=Address{firstLine='Somewhere', secondLine='Else'}, number=1}
    

    If you don't like annotations you can map things manually:

        CsvRoutines routines = new CsvRoutines();
        ColumnMapper mapper = routines.getColumnMapper();
    
        mapper.attributeToColumnName("name", "name");
        mapper.attributeToColumnName("gender", "gender");
        mapper.attributeToColumnName("number", "number");
        mapper.attributeToColumnName("address.firstLine", "address_first_line");
        mapper.attributeToColumnName("address.secondLine", "address_second_line");
    
        for (User user : routines.iterate(User.class, input)) {
            System.out.println(user.toString());
        }
    

    Hope it helps.

    Disclaimer: I'm the author of this lib. It's open-source and free (Apache 2.0 license)