super csv nested bean

2020-05-01 07:26发布

问题:

I have a csv

id,name,description,price,date,name,address
1,SuperCsv,Write csv file,1234.56,28/03/2016,amar,jp nagar

I want to read it and store it to json file. I have created two bean course(id,name,description,price,date) and person(name,address)

on reading by bean reader i'm not able to set the person address. The (beautified) output is

Course [id=1,
        name=SuperCsv,
        description=Write csv file,
        price=1234.56,
        date=Mon Mar 28 00:00:00 IST 2016,
        person=[
            Person [name=amar, address=null],
            Person [name=null, address=jpnagar]
        ]
]

I want the adress to set with name

My code:

public static void readCsv(String csvFileName) throws IOException {

        ICsvBeanReader beanReader = null;
        try {
            beanReader = new CsvBeanReader(new FileReader(csvFileName), CsvPreference.STANDARD_PREFERENCE);

            // the header elements are used to map the values to the bean (names must match)
            final String[] header = beanReader.getHeader(true);
            final CellProcessor[] processors = getProcessors();

            final String[] fieldMapping = new String[header.length];

            for (int i = 0; i < header.length; i++) {
                if (i < 5) {
                    // normal mappings
                    fieldMapping[i] = header[i];

                } else {
                    // attribute mappings
                    fieldMapping[i] = "addAttribute";

                }}
            ObjectMapper mapper=new ObjectMapper();
            Course course;
            List<Course> courseList=new ArrayList<Course>();
            while ((course = beanReader.read(Course.class, fieldMapping, processors)) != null) {
                // process course
                System.out.println(course);
                courseList.add(course);


            }
private static CellProcessor[] getProcessors(){

        final CellProcessor parsePerson = new CellProcessorAdaptor() {
            public Object execute(Object value, CsvContext context) {
                return new Person((String) value,null);
            }
        };  

        final CellProcessor parsePersonAddress = new CellProcessorAdaptor() {
            public Object execute(Object value, CsvContext context) {
                return new Person(null,(String) value);
            }
        };

        return new CellProcessor[] {
                new ParseInt(),
                new NotNull(),
                new Optional(),
                new ParseDouble(),
                new ParseDate("dd/MM/yyyy"),
                new Optional(parsePerson),
                new Optional(parsePersonAddress)        
        };

回答1:

SuperCSV is the first parser I have seen that lets you create an object within an object.

for what you are wanting you can try Apache Commons CSV or openCSV (CSVToBean) to map but to do this you need to have the setters of the inner class (setName, setAddress) in the outer class so the CSVToBean to pick it up. That may or may not work.

What I normally tell people is to have a plain POJO that has all the fields in the csv - a data transfer object. Let the parser create that then use a utility/builder class convert the plain POJO into the nested POJO you want.