Java 具有复杂bean结构的openCSV

Java 具有复杂bean结构的openCSV,java,opencsv,Java,Opencsv,我尝试用openCSV映射嵌套bean结构。我找到了注释,但是如果嵌套bean被多次使用,这似乎不起作用 我有什么办法来解决这个问题 示例(根据上面链接的文档改编) 要映射的数据结构: title,author1 given name,author1 surname,author2 given name,author2 surname Space Opera 2.0,Andrew,Jones,Hanna,Smith 我想买以下的豆子 public class Book { @CsvBi

我尝试用openCSV映射嵌套bean结构。我找到了注释,但是如果嵌套bean被多次使用,这似乎不起作用

我有什么办法来解决这个问题

示例(根据上面链接的文档改编)

要映射的数据结构:

title,author1 given name,author1 surname,author2 given name,author2 surname
Space Opera 2.0,Andrew,Jones,Hanna,Smith
我想买以下的豆子

public class Book {
    @CsvBindByName
    private String title;

    // TODO: How to bind author1 and author2?
    private Author author1;
    private Author author2;

    // Accessor methods go here.
}

public class Author {
    // TODO: can I somehow use a prefix/Regex for the column here to differentiate between author1 and author2?
    @CsvBindByName(column = "author[1/2] given name")
    private String givenName;

    @CsvBindByName(column = "author[1/2] surname")
    private String surname;

    // Accessor methods go here.
}

您可以使用自定义的“ColumnPositionMappingStrategy”。重写“populateNewBean”方法,该方法接受字符串[](csv的行),并可以从中形成任何对象


“@CsvRecurse”应该适用于OpenCSV 5.0 btw。

这里是另一个选项:

opencsv库有很多有用且灵活的注释,但是在这个特定的例子中,我不会使用任何注释

相反,我将使用opencsv类。使用此选项将允许您保留两个
书籍
作者
类。我唯一要做的更改是向每个类添加构造函数,如下所示:

书籍:

作者:

public class Author {

    private final String givenName;
    private final String surname;

    public Author(String givenName, String surname) {
        this.givenName = givenName;
        this.surname = surname;
    }

    public String getGivenName() {
        return givenName;
    }

    public String getSurname() {
        return surname;
    }

}
要从CSV文件填充
Book
对象列表,请执行以下操作:

import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import com.opencsv.CSVReaderHeaderAware;
import com.opencsv.exceptions.CsvValidationException;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

...

    public static void main(String[] args) throws FileNotFoundException, 
            IOException, CsvValidationException {
        String bookFile = "/path/to/titles.csv";

        CSVReaderHeaderAware csvReader = new CSVReaderHeaderAware(new FileReader(bookFile));

        List<Book> books = new ArrayList();

        Map<String, String> bookRecord;
        while ((bookRecord = csvReader.readMap()) != null) {
            books.add(handleBook(bookRecord));
        }
    }

    private static Book handleBook(Map<String, String> bookRecord) {
        Author author1 = new Author(
                bookRecord.get("author1 given name"),
                bookRecord.get("author1 surname")
        );

        Author author2 = new Author(
                bookRecord.get("author2 given name"),
                bookRecord.get("author2 surname")
        );

        return new Book(bookRecord.get("title"), author1, author2);
    }
import java.util.Map;
导入java.util.List;
导入java.util.ArrayList;
导入com.opencsv.csvreaderheaderware;
导入com.opencsv.exceptions.CsvValidationException;
导入java.io.FileNotFoundException;
导入java.io.FileReader;
导入java.io.IOException;
...
公共静态void main(字符串[]args)引发FileNotFoundException,
IOException,CsvValidationException{
字符串bookFile=“/path/to/titles.csv”;
csvreaderheaderware csvReader=新的csvreaderheaderware(新文件阅读器(bookFile));
List books=new ArrayList();
地图记录;
而((bookRecord=csvReader.readMap())!=null){
书籍。添加(手把簿(bookRecord));
}
}
私人静态书本把手(地图书记录){
author1=新作者(
bookRecord.get(“author1名”),
bookRecord.get(“author1姓氏”)
);
author2=新作者(
bookRecord.get(“author2名”),
bookRecord.get(“author2姓氏”)
);
归还新书(bookRecord.get(“title”)、作者1、作者2);
}
CSV文件中的每一行数据都被读入
映射
对象,其中文件头是映射的键(您需要确保文件头是唯一的)。地图对应的值表示CSV文件中的一行数据


唯一的缺点是,您可能需要将字符串值强制转换为其他数据类型—尽管在本例中不是这样,因为数据项已经是字符串。

谢谢您的建议。我将检查自定义映射策略是否可以解决我的问题(但我可能会选择
HeaderNameBaseMappingStrategy
,因为列的顺序可以在输入中更改)。但是,如果可能的话,我更愿意使用
@CsvRecurse
。但它似乎并没有完成我需要它做的事情:它似乎只适用于同一类类型最多有1个变量的情况,对吗?因此,如果我有1个
Author
变量,它将非常有效。但是,有没有一种方法可以将它与我的源bean中的2个
Author
变量一起使用呢?
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import com.opencsv.CSVReaderHeaderAware;
import com.opencsv.exceptions.CsvValidationException;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

...

    public static void main(String[] args) throws FileNotFoundException, 
            IOException, CsvValidationException {
        String bookFile = "/path/to/titles.csv";

        CSVReaderHeaderAware csvReader = new CSVReaderHeaderAware(new FileReader(bookFile));

        List<Book> books = new ArrayList();

        Map<String, String> bookRecord;
        while ((bookRecord = csvReader.readMap()) != null) {
            books.add(handleBook(bookRecord));
        }
    }

    private static Book handleBook(Map<String, String> bookRecord) {
        Author author1 = new Author(
                bookRecord.get("author1 given name"),
                bookRecord.get("author1 surname")
        );

        Author author2 = new Author(
                bookRecord.get("author2 given name"),
                bookRecord.get("author2 surname")
        );

        return new Book(bookRecord.get("title"), author1, author2);
    }