You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用CSV Helper导出多层嵌套对象的非重复CSV格式数据?

多层级对象导出CSV(顶层数据去重)

问题背景

给定以下C#类结构:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set;}
    public List<Book> Books { get; set; }
}
public class Book
{
    public Guid Id { get; set; }
    public string Name { get; set;}
    public List<Chapter> Chapters{ get; set; }
    public List<Author> Authors { get; set; }
}

public class Author 
{
    public string Name { get; set; }
}

public class Chapter
{
    public string Name { get; set;}
}

需要导出CSV文件,要求顶层Person的personId和Name字段不重复,关联的Book、Author、Chapter对应多行展示,重复的上层字段留空,示例格式如下:

personId,Name,BookName,AuthorName,ChapterName
1,name1,Book1Name,AuthorName1,chapterName1
,,,AuthorName2,
,,Book2Name,AuthorName1,chapterName1
2,name2,Book3Name,AuthorName3,chapterName3
3,name3,Book1Name,,chapterName4
,,,,chapterName5

解决方案

要实现这种格式,核心是遍历所有层级对象,为每个需单独成行的节点构建CSV记录,重复的上层字段留空。以下是手动构建记录并写入CSV的实现代码:

实现代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

public class CsvExporter
{
    public void ExportPersonsToCsv(List<Person> persons, string filePath)
    {
        // 定义CSV表头
        var headers = new List<string> { "personId", "Name", "BookName", "AuthorName", "ChapterName" };

        using (var writer = new StreamWriter(filePath))
        {
            // 写入表头
            writer.WriteLine(string.Join(",", headers));

            foreach (var person in persons)
            {
                bool isFirstPersonRow = true;

                foreach (var book in person.Books ?? Enumerable.Empty<Book>())
                {
                    bool isFirstBookRow = true;

                    // 先处理当前书籍的所有作者行
                    foreach (var author in book.Authors ?? Enumerable.Empty<Author>())
                    {
                        var row = new List<string>();
                        // 填充Person字段:仅第一行写入,后续留空
                        if (isFirstPersonRow && isFirstBookRow)
                        {
                            row.Add(person.Id.ToString());
                            row.Add(person.Name ?? string.Empty);
                            isFirstPersonRow = false;
                        }
                        else
                        {
                            row.Add(string.Empty);
                            row.Add(string.Empty);
                        }
                        // 填充Book字段:仅当前书籍的第一行写入,后续留空
                        row.Add(isFirstBookRow ? (book.Name ?? string.Empty) : string.Empty);
                        isFirstBookRow = false;
                        // 填充Author和Chapter字段
                        row.Add(author.Name ?? string.Empty);
                        row.Add(string.Empty);

                        // 字段加双引号,避免含逗号导致格式错误
                        writer.WriteLine(string.Join(",", row.Select(f => $"\"{f}\"")));
                    }

                    // 再处理当前书籍的所有章节行
                    foreach (var chapter in book.Chapters ?? Enumerable.Empty<Chapter>())
                    {
                        var row = new List<string>
                        {
                            string.Empty, string.Empty, string.Empty, string.Empty,
                            chapter.Name ?? string.Empty
                        };

                        writer.WriteLine(string.Join(",", row.Select(f => $"\"{f}\"")));
                    }
                }
            }
        }
    }
}

// 使用示例
// var persons = new List<Person> { /* 初始化你的数据 */ };
// var exporter = new CsvExporter();
// exporter.ExportPersonsToCsv(persons, @"C:\output.csv");

代码说明

  1. 表头写入:先定义CSV列名,写入文件第一行;
  2. 层级遍历逻辑:
    • 遍历每个Person,标记是否为该Person的首行;
    • 遍历每个Book,标记是否为该Book的首行;
    • 先处理Book下的所有Author:首行填充Person和Book字段,后续仅填充Author字段;
    • 再处理Book下的所有Chapter:所有上层字段留空,仅填充Chapter字段;
  3. 格式兼容:每个字段用双引号包裹,避免字段含逗号导致CSV格式紊乱。

如果需要调整Author和Chapter的关联逻辑(比如每个Author对应所有Chapter),只需修改内层循环的组合方式即可。


内容的提问来源于stack exchange,提问作者Morks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:02:36