Search code examples
c#csvhelper

CsvHelper write mapper one property to multiple columns


I'm using csvHelper (version 2.8.4) to write a class to csv. My class looks like this:

public class classA
{
   public int Amount { get; set; }
   public Dictionary<string, string> Dict{ get; set; }
}

Is it possible to write a mapper that maps Dict property to multiple columns? using some sort of converter?

for example if the class has the values:
Amount = 15
Dict = new Dictionary<string,string>{["a1"] = "a2",["b1"] = "b2"}

I want the resulting csv to be:

Amount,a1,b1
15,a2,b2

Thanks!


Solution

  • Possibly the easiest way is going to be to manually write out the dictionary part.

    *** Update to work with CsvHelper Version 2.8.4 ***

    void Main()
    {
        var records = new List<classA>
        {
            new classA {
                Amount = 15,
                Dict = new Dictionary<string,string>{["a1"] = "a2",["b1"] = "b2"}
            }
        };
        
        using (var csv = new CsvWriter(Console.Out))
        {
            var dict = records.First().Dict;
    
            var properties = typeof(classA).GetProperties();
            
            foreach (PropertyInfo property in properties)
            {
                if (property.Name != "Dict")
                {
                    csv.WriteField(property.Name);
                }
            }
    
            foreach (var item in dict)
            {
                csv.WriteField(item.Key);
            }
    
            csv.NextRecord();
    
            foreach (var record in records)
            {
                foreach (PropertyInfo property in properties)
                {
                    if (property.Name != "Dict")
                    {
                        csv.WriteField(property.GetValue(record));
                    }
                }
    
                foreach (var item in record.Dict)
                {
                    csv.WriteField(item.Value);
                }
    
                csv.NextRecord();
            }
        }
    }
    
    // You can define other methods, fields, classes and namespaces here
    
    public class classA
    {
        public int Amount { get; set; }
        public Dictionary<string, string> Dict { get; set; }
    }
    

    *** Works for current Version 27.2.1 ***

    void Main()
    {
        var records = new List<classA>
        {
            new classA { Amount = 15, Dict = new Dictionary<string,string>{["a1"] = "a2",["b1"] = "b2"} },
        };
    
        using (var csv = new CsvWriter(Console.Out, CultureInfo.InvariantCulture))
        {
            var dict = records.First().Dict;
            
            csv.WriteHeader<classA>();
            
            foreach (var item in dict)
            {
                csv.WriteField(item.Key);   
            }
            
            csv.NextRecord();
            
            foreach (var record in records)
            {
                csv.WriteRecord(record);
    
                foreach (var item in record.Dict)
                {
                    csv.WriteField(item.Value);
                }
                
                csv.NextRecord();
            }       
        }
    }
    
    public class classA
    {
        public int Amount { get; set; }
        public Dictionary<string, string> Dict { get; set; }
    }