复杂的Java对象到CSV

时间:2015-11-18 19:04:10

标签: java csv pojo supercsv

我正在尝试从相当复杂的Java对象生成CSV文件。该对象是一个包含一些属性的会话,一个包含一些属性的字符串和消息列表以及一个包含某些属性的注释列表。

会话类如下;

public class Session {

    private Long id;

    private Date startDate;

    private Date endDate;

    private List<Message> messages;

    private List<String> participants;

    public TweetSession() {
    }  

    public TweetSession(Date startDate, List<Message> messages, List<String>     participants) {
        this.startDate = startDate;
        this.messages = messages;
        this.participants = participants;
    }

    public Long getId() {
        return id;
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

    public List<Message> getMessages() {
        return messages;
    }

    public void setMessage(List<Message> messages) {
        this.message = message;
    }

    public List<String> getParticipants() {
        return participants;
    }

    public void setParticipants(List<String> participants) {
        this.participants = participants;
    }
}

消息类如下;

public class Message {

    private Long id;

    private Session session;

    private Date date;

    private String participant;

    private String content;

    private List<Comment> comments;

    public Message() {
    }

    public Message(String participant, Session session, Date date, String content) {
        this.participant = participant;
        this.session = session;
        this.content = content;
        this.date = date;
        this.comments = new ArrayList<>();
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getParticipant() {
        return participant;
    }

    public void setParticipant(String participant) {
        this.participant = participant;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public List<Comment> getComments() {
        return comments;
    }

    public void setComments(List<Comment> comments) {
        this.comments = comments;
    }

    public void addComment(Comment comment) {
        this.comments.add(comment);
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public TweetSession getSession() {
        return session;
    }

    public void setSession(TweetSession session) {
        this.session = session;
    }
}

评论类;

public class Comment {

    private Long id;

    private Message message;

    private String participant;

    private String message;

    private Date date;

    public Comment() {
    }

    public Comment(String participant, Message message, String content, Date date) {
        this.participant = participant;
        this.content = content;
        this.message = message;
        this.date = date;
    }

    public String getParticipant() {
        return participant;
    }

    public void setParticipant(String participant) {
        this.participant = participant;
    }

    public Message getMessage() {
        return message;
    }

    public void setMessage(Message message) {
        this.message = message;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}   

我想知道是否可以将其映射到CSV文件。当我将会话对象转换为JSON格式并将该JSON转换为在线生成器中的CSV时,我得到了正确的输出,所以我认为它必须是可能的。我只是不知道如何。 我试过像这样使用net.sf.supercsv库;

public void generateCSV(Session session, HttpServletResponse response) throws IOException {
    String csvFileName = "session.csv";
    response.setContentType("text/csv");

    String headerKey = "Content-Disposition";
    String headerValue = String.format("attachment; filename=\"%s\"",
            csvFileName);
    response.setHeader(headerKey, headerValue);

    ICsvBeanWriter csvWriter = new CsvBeanWriter(response.getWriter(),
            CsvPreference.STANDARD_PREFERENCE);

    // Generate header for the CSV
    Field fields[] = session.getClass().getDeclaredFields();
    String[] header = new String[fields.length];
    for (int i = 0; i < fields.length; i++) {
        header[i] = fields[i].getName();
    }

    csvWriter.writeHeader(header);

    // Generate CSV content from data
    csvWriter.write(session, header);

    csvWriter.close();
}

但这当然不能给出理想的结果。

有人能指出我正确的方向吗?

提前致谢,

尼尔斯

修改

这是一个JSON格式的示例会话:

{
    "id": 22,
    "startDate": 1447368081000,
    "endDate": null,
    "messages": [
        {
            "id": 10,
            "date": 1447368159000,
            "participant": "1",
            "content": "This is a message",
            "comments": []
        },
        {
            "id": 11,
            "date": 1447368168000,
            "participant": "1",
            "content": "This is also a message",
            "comments": []
        },
        {
            "id": 12,
            "date": 1447368179000,
            "participant": "1",
            "content": "This is another message",
            "comments": [
                {
                    "id": 10,
                    "participant": "1",
                    "message": "This is a comment",
                    "date": 1447368227000
                },
                {
                    "id": 11,
                    "participant": "1",
                    "message": "This is also a comment",
                    "date": 1447368234000
                }
            ]
        }
    ],
    "participants": [
        "1",
        "23"
    ]
}

当我将其转换为CSV时,我会得到类似的结果:

CSV

确实开始考虑(单个)CSV可能不是解决此问题的最佳方法。

5 个答案:

答案 0 :(得分:6)

您拥有的数据中包含许多1:n依赖项,并且不适合单个 CSV文件。

我用过或看过用过的方法:

  • 一个带有Session自己数据的“混合”CSV,即第一列中的idstartDateendDate,然后是两列消息和参与者打印为JSON

    "123", "2015-11-17", "2015-11-18", "[{id: 345, date: ...}, {id: 789, date: ...}]", "[...]"
    

    (请注意,您需要使用一个好的CSV库来逃避包含," s的值

  • 多个CSV文件 - 模仿您为您的结构建立关系数据库的模型,即

    • sessions.csv包含idstartDateendDate
    • messages.csv包含idsession_iddate,...
    • ...

    然后将它们压缩为单个文件下载

  • 要求您的用户提供更精确的规范 - 努力找出他们打算对数据做些什么,然后以一种格式让他们“查看”数据,使他们能够轻松阅读 - 只是顺便说一下创建数据库视图和报告,为用户提供面向任务的数据视图。

答案 1 :(得分:2)

我们使用openCSV

  

com.opencsv.bean.BeanToCsv实现此目的

   public void exportIronData(String destinationFilePath,
        List<ExportIronDataFileFormatDTO> dataList) throws Exception {
    try {
        if (validationUtil.isNullOrEmpty(destinationFilePath)
                || validationUtil.isNullOrEmpty(dataList)) {
            return;
        }
        ColumnPositionMappingStrategy<ExportIronDataFileFormatDTO> strategy = new ColumnPositionMappingStrategy<ExportIronDataFileFormatDTO>();
        strategy.setType(ExportIronDataFileFormatDTO.class);
        String[] columns = IlmcrCsvFileConstants.EXPORT_IRONDATA_COLUMN_HEADERS;
        strategy.setColumnMapping(columns);
        CSVWriter writer = new CSVWriter(
                new FileWriter(destinationFilePath),
                IlmcrCsvFileConstants.exportIronDataSeperator,
                CSVWriter.NO_ESCAPE_CHARACTER, System.getProperty("line.separator"));
        BeanToCsv<ExportIronDataFileFormatDTO> exportFormat = new BeanToCsv<ExportIronDataFileFormatDTO>();
        exportFormat.write(strategy, writer, dataList);
        writer.flush();
        writer.close();
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
}

如果您还有其他需要,请告诉我

答案 2 :(得分:1)

有一个名为json2flat.的图书馆 它的作用是需要一个复杂的JSON文档并将其转换为CSV格式。

所以你需要做的是将你的java对象转换为JSON格式。在它之后 你需要将生成的JSON传递给库,它返回一个2D
表示JSON,你也可以从中获取csv。

这个图书馆并不成熟,但仍然很有希望 你应该试一试。

答案 3 :(得分:0)

您应该使用混合CSV格式。我有同样的问题所以我创建了一个轻量级框架。您可以复制源代码或示例:https://github.com/abhisoni96/dev-tools

您可以为每个基于集合的数据成员创建自己的格式化程序。请参考以上链接中的示例。

答案 4 :(得分:-1)

我建议改用Apache Commons CSV。我们在几个项目中使用过它,包括管理我们的邮件列表。

 Reader in = new StringReader("a,b,c");
 for (CSVRecord record : CSVFormat.DEFAULT.parse(in)) {
     for (String field : record) {
         System.out.print("\"" + field + "\", ");
     }
     System.out.println();
 }
Output: "a", "b", "c",