Search code examples
csvparsingcsvhelper

CsvHelper mapping issue


I have a question related to CsvHelper library and I cannot figure out how to map a csv file to the following MyClass object. the csv file look like:

id, Property1, property2....
1, x, a,b,c
2,x, d,f
3, y, g,h,i,j,k 
...

Which I would like to parse to the following classes

public class MyClass
{
    public string Id { get; set; }

    public List<Custom> MyCustoms { get; set; }
}

public class Custom
{
    public string Property1 { get; set; }

    public List<string> Property2 { get; set; }
}

Solution

  • ConvertUsing is going to be the easiest way to map this.

    public class Program
    {
        static void Main(string[] args)
        {
            using (var stream = new MemoryStream())
            using (var writer = new StreamWriter(stream))
            using (var reader = new StreamReader(stream))
            using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
            {
                writer.WriteLine("Id,Property1,Property2,Property3,Property4,Property5,Property6");
                writer.WriteLine("1,x,a,b,c");
                writer.WriteLine("2,x,d,f");
                writer.WriteLine("3,y,g,h,i,j,k");
                writer.Flush();
                stream.Position = 0;
    
                var test = csv.Configuration.RegisterClassMap<MyClassMap>();
    
                var records = csv.GetRecords<MyClass>().ToList();
            } 
        }
    }
    
    public class MyClassMap: ClassMap<MyClass>
    {
        public MyClassMap()
        {
            Map(m => m.Id);
            Map(m => m.MyCustoms).ConvertUsing(row =>
            {
                var custom = new Custom 
                { 
                    Property1 = row["Property1"], 
                    Property2 = new List<string>() 
                };
    
                var index = 2;
    
                while (row.TryGetField(typeof(string), index, out var property))
                {
                    custom.Property2.Add((string)property);
                    index++;
                }
    
                return new List<Custom> { custom };
            });
        }
    }
    
    public class MyClass
    {
        public string Id { get; set; }
    
        public List<Custom> MyCustoms { get; set; }
    }
    
    public class Custom
    {
        public string Property1 { get; set; }
    
        public List<string> Property2 { get; set; }
    }