Search code examples
jsoncsvjacksonpojojackson-modules

CsvParser "No suitable constructor found for type"


I'm trying to read a simple CSV file using the Jackson CsvParser. I've followed the tutorial, but I keep getting the following error:

com.fasterxml.jackson.databind.RuntimeJsonMappingException: No suitable constructor found for type [simple type, class data.MyPojo$MyPojo]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: java.io.InputStreamReader@3d362683; line: 2, column: 1]
at com.fasterxml.jackson.databind.MappingIterator.next(MappingIterator.java:121)

The CSV file MYFILE.CSV is really simple:

FirstAddress,SecondAddress
Blah,Blah
Etc,Etc

And so is the code:

public class MyPojoLookup {
    private final static String FILENAME = "/MYFILE.CSV";
    private final static CsvMapper mapper = new CsvMapper();

    static {
        CsvSchema schema = CsvSchema.emptySchema().withHeader();

        InputStream input = (MyPojoLookup.class.getResourceAsStream(FILENAME));

        MappingIterator<MyPojo> it;
        try {
            it = mapper.reader(MyPojo.class).with(schema).readValues(input);

            while (it.hasNext()){
                MyPojo row = it.next();
                log.info(row.toString());
            }
        } catch (Exception e) {
            log.error("Cannot load the addresses", e);
            System.exit(-1);
        }
    }

    private class MyPojo {
        public String address1;
        public String address2;

        public MyPojo(String address1, String address2) {
            super();
            this.address1 = address1;
            this.address2 = address2;
        }

        @Override
        public String toString() {
            return "MyPojo ["address1=" + address1 + ", address2=" + address2 + "]";
        }
    }
}

Solution

  • There are three issues with your code:

    1) You need to pass the properties that are going to be read to the CSV schema, in your case these are address1 and address2:

    CsvSchema schema = CsvSchema.builder()
                                .addColumn("address1")
                                .addColumn("address2")
                                .build();
    

    2) Your inner class is not marked as static, check this link that explains why this is necessary.

    3) You are missing a default constructor.

    Here's a complete listing with all fixes applied:

    import com.fasterxml.jackson.databind.MappingIterator;
    import com.fasterxml.jackson.dataformat.csv.CsvMapper;
    import com.fasterxml.jackson.dataformat.csv.CsvSchema;  
    import java.io.InputStream;
    
    public class MyPojoLookup {
    
        private final static String FILENAME = "/MYFILE.CSV";
        private final static CsvMapper mapper = new CsvMapper();
    
        public static void main(String[] args) {
            CsvSchema schema = CsvSchema.builder().addColumn("address1").addColumn("address2").build();
    
            InputStream input = (MyPojoLookup.class.getResourceAsStream(FILENAME));
    
            MappingIterator<MyPojo> it;
            try {
                it = mapper.reader(MyPojo.class).with(schema).readValues(input);
    
                while (it.hasNext()){
                    MyPojo row = it.next();
                    System.out.println(row.toString());
                }
            } catch (Exception e) {
                System.out.println("Cannot load the addresses");
                e.printStackTrace();
                System.exit(-1);
            }
        }
    
        private static class MyPojo {
            public String address1;
            public String address2;
    
            public MyPojo() {}
    
            public MyPojo(String address1, String address2) {
                super();
                this.address1 = address1;
                this.address2 = address2;
            }
    
            @Override
            public String toString() {
                return "MyPojo [address1=" + address1 + ", address2=" + address2 + "]";
            }
        }
    }