CsvHelper 尝试在 csv 中导出一个包含另一个列表 .net 的列表

CsvHelper try to export in csv a list which contain another list .net

我在 .Net Framework 中实现了一个 Web api,使用 csvHelper 导出一个 csv。

我有 类

public class StudentInfo
{
    public Student Student {get;set;}
    public Courses[] Courses { get; set; }
}

public class Student
{
    public string Id {get;set;}
    public string Name{ get; set; }
}

public class Course
{
   public string CourseId {get;set;}
   public string CourseName{ get; set; }
}

我有一个方法return一个列表

public List<StudentInfo> FetchStudentInfo()
{
    //bla bla 
}

现在我想使用 csvHelper

以 csv 格式导出列表

这是我的代码

List<StudentInfo> records = _service.FetchStudentInfo()
    using (StreamWriter sw = new StreamWriter(memoryStream))
    {
        using (var csv = new CsvWriter(sw))
        {        
            csv.WriteRecords(records);
            sw.Flush();
        }
    }

但此代码仅导出到 csv 对象 Students。 如何将每个学生的课程列表导出到 csv 中?

例如 12 jim java c# python

如果我尝试

foreach(var item in records)
{
    csvWriter.WriteRecords(item.Student);//I have compile error because it want to pass an IEnumerable
    csvWriter.WriteRecords(item.Courses);
}

CSV 格式不能表示列表中的列表。在导出后读取 CSV 时,我没有弄清楚如何解释数据。

XML 或 JSON 必须更喜欢将复杂数据导出到平面文件中。

如果您真的想获取 CSV 文件,则必须使用 2 个不同的分隔符来区分 2 个 class(例如:',' 代表 StudentInfo,';' 代表课程)。

之后我将创建一个 class 来表示 CSV 数据:

public class StudentInfoCsv
{
    public Student Student {get;set;}
    public string Courses { get; set; }
}

List<StudentInfoCsv> csvData = new List<StudentInfoCsv>
foreach(var item in records)
{
    StudentInfoCsv.Add(new StudentInfoCsv()
    {
        Student = item.Student,
        Courses = CsvSerializer.SerializeToCsv(item.Courses)
    }
}
csvWriter.WriteRecords(csvData);

解决方案是

                       foreach (StudentInfo item in records)
                        {
                            csvWriter.WriteField(item.Student.Id);
                            csvWriter.WriteField(item.Student.Name);

                            foreach (var row in item.Courses)
                            {
                                csvWriter.WriteField(row.CourseName);
                            }
                            csvWriter.NextRecord();
                        }

输出将是

12 jim java c# python

@dimmits 的回答效果很好,而且易于阅读。我想我会提供另一个更基于配置的选项。它确实需要修改 StudentInfo class.

public class Program
{
    public static void Main(string[] args)
    {
        var studentInfos = FetchStudentInfo();

        using (var csv = new CsvWriter(Console.Out))
        {
            csv.Configuration.HasHeaderRecord = false;
            csv.Configuration.RegisterClassMap<StudentInfoMap>();

            csv.WriteRecords(studentInfos);
        }

        Console.ReadKey();
    }

    public static List<StudentInfo> FetchStudentInfo()
    {
        Course[] courses1 = { new Course { CourseId = "1", CourseName = "java" }, new Course { CourseId = "2", CourseName = "c#" }, new Course { CourseId = "3", CourseName = "python" } };
        Course[] courses2 = { new Course { CourseId = "1", CourseName = "java" }, new Course { CourseId = "2", CourseName = "c#" } };
        return new List<StudentInfo>
        {
            new StudentInfo{ Student = new Student{Id = "12", Name = "Jim"}, Courses = courses1 },
            new StudentInfo{ Student = new Student{Id = "45", Name = "Dave"}, Courses = courses2 }
        };
    }
}

public class StudentInfoMap : ClassMap<StudentInfo>
{
    public StudentInfoMap()
    {
        References<StudentMap>(m => m.Student);
        Map(m => m.CourseNames).Index(3);
    }
}

public class StudentMap : ClassMap<Student>
{
    public StudentMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
    }
}

public class StudentInfo
{
    public Student Student { get; set; }
    public Course[] Courses { get; set; }
    public string[] CourseNames { get { return Courses.Select(c => c.CourseName).ToArray(); } }
}

public class Student
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public class Course
{
    public string CourseId { get; set; }
    public string CourseName { get; set; }
}