Click here to Skip to main content
15,849,907 members
Articles / General Programming / File
Tip/Trick

Quick, Simple and Elegant way to convert C# data model to CSV

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
18 Aug 2019CPOL1 min read 9.5K   114   6   6
CSV file generator using simplistic approach

Introduction

Converts a c# data model to csv formatted file. I know there are tools which does this but I had a situation where I can't use third party libraries or tools and I had to write code for a legacy application.

Could be a good starting point or use this as template.

All it does is pass on the data to the model and it converts it to CSV data or file.

Background

There are multiple ways to achieve this one of them is Reflection where we use reflection to get the types of the properties and then get the data, loop through all properties and generate the data.

In this article I would specify a simple and elegant way to achieve the same. The approach really depends on the situation and problem you have.

Using the code

Let's start with some test data as input:

C++
[
  {
    "MemberName": "David",
    "MemberNumber": "1"
  },
  {
    "MemberName": "Joseph",
    "MemberNumber": "2"
  }
]

Deserialize the data:

C++
var listMemberData=JsonConvert.DeserializeObject<IEnumerable<MemberData>>(File.ReadAllText("MemberData.json"));

Define ColumnDataMapper - Maps each of the cell:

C++
public class ColumnDataMapper
    {
        public string HeaderName { get; set; }
        public Func<MemberData, string> Extractor { get; set; }
    }

Now define the initial structure of our Member Data (like a table having row and column):

C++
public static readonly IEnumerable<ColumnDataMapper> MemberDataMappers = new[]
        {
            new ColumnDataMapper
            {
                HeaderName = "Member Number",
                Extractor = obj => obj.MemberNumber.ToString()
            },
            new ColumnDataMapper
            {
                HeaderName = "Member Name",
                Extractor = obj => obj.MemberName
            }
        };

Generate all data:

C++
public static StringBuilder GenerateFileContent(IEnumerable<MemberData> listMemberData)
        {
            StringBuilder sbOutput = new StringBuilder();

            //Generate Header
            sbOutput.AppendLine(string.Join(DataSeparator, DataMappers.MemberDataMappers.Select(p => p.HeaderName)));

            //Generate rows
            foreach (var memberData in listMemberData)
            {
                sbOutput.AppendLine(string.Join(DataSeparator, DataMappers.MemberDataMappers.Select(p=>p.Extractor(memberData))));
            }
            return sbOutput;
        }

Points of Interest

For simple structure we could go with this method but for complex objects I'd prefer Reflection or open source tool like FileHelpers Library.

History

Initial article

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionCSV standard Pin
wvd_vegt20-Aug-19 14:12
professionalwvd_vegt20-Aug-19 14:12 
AnswerRe: CSV standard Pin
rohitsies25-Aug-19 16:45
rohitsies25-Aug-19 16:45 
QuestionAn Alternative Approach Pin
George Swan19-Aug-19 11:22
mveGeorge Swan19-Aug-19 11:22 
AnswerRe: An Alternative Approach Pin
rohitsies19-Aug-19 14:23
rohitsies19-Aug-19 14:23 
GeneralRe: An Alternative Approach Pin
George Swan19-Aug-19 19:54
mveGeorge Swan19-Aug-19 19:54 

Thanks, you make a good point about the header. I should add that my approach is not new, there is an excellent article on Code Project Create CSV from JSON in C# that converts a DataTable to a Csv file. It is possible to change the example to an extension method but it's probably not robust enough for that.

C#
public static class Extensions
   {
       public static string ConvertToCsv(this DataTable dt, string separator)
       {
           StringBuilder sb = new StringBuilder();

           //Generate Header
           var columnNames = dt.Columns.Cast<DataColumn>().
                                       Select(c => c.ColumnName);
           sb.AppendLine(string.Join(separator, columnNames));

           //Generate body text
           foreach (DataRow row in dt.Rows)
           {
               var items = row.ItemArray.Select(o => o.ToString());
               sb.AppendLine(string.Join(separator, items));
           }
           return sb.ToString();
       }

   }
It could be used like this.
C#
var jsonContent = File.ReadAllText("TestData/MemberData.json");
//convert to DataTable
DataTable dt = JsonConvert.DeserializeObject<DataTable>(jsonContent);
string csvString = dt.ConvertToCsv(";");


GeneralRe: An Alternative Approach Pin
rohitsies19-Aug-19 23:38
rohitsies19-Aug-19 23:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.