-1

Is there any library out there that can serialize objects with array properties to .csv?

Let's say I have this model:

public class Product
{
    public string ProductName { get; set; }
    public int InStock { get; set; }
    public double Price { get; set; }
    ...
    public string[] AvailableVariants { get; set; }
}

Would something like that be possible to do?

Edit: I need to present some data in a csv/excel format. The thing is, I'm not sure if there is a simple way of achieving what I want with CSV serialization libraries or if I should rather focus on writing an Excel native file.

An example of result I'm looking for:

Product Name    In Stock    Price   Variants
ABC 241 200 Normal
CAB 300 300 Normal
            Red
            Blue
CBA 125 100 Normal
            White
            Awesome
            Red
ACB 606 75  Normal
            Small
            Large
            X-Large

What would be the most efficient way to do this?

Reynevan
  • 1,475
  • 1
  • 18
  • 35
  • 3
    What did Google say about this? – Chetan Jun 20 '17 at 05:06
  • [duplicated] check https://stackoverflow.com/questions/25683161/fastest-way-to-convert-a-list-of-objects-to-csv-with-each-object-values-in-a-new – msd Jun 20 '17 at 05:08
  • 3
    Possible duplicate of [Fastest way to convert a list of objects to csv with each object values in a new line](https://stackoverflow.com/questions/25683161/fastest-way-to-convert-a-list-of-objects-to-csv-with-each-object-values-in-a-new) – Vahid K. Jun 20 '17 at 05:08
  • @msd this question doesn't say anything about `CsvSerialized` being able to save objects in a format I want to save them in. – Reynevan Jun 20 '17 at 05:19
  • @Reynevan Okay, you are seeking for a library right? check [nuget](https://www.nuget.org/packages?q=csv) – msd Jun 20 '17 at 05:34
  • @msd I edited my question. – Reynevan Jun 20 '17 at 05:46

2 Answers2

0

I'm not aware of any libraries that will do this, here's a console example of how I'd approach writing/reading from a CSV:

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

namespace TestingProduct
{
    class TestingProduct
    {
        public class Product
        {
            public string ProductName { get; set; }
            public int InStock { get; set; }
            public double Price { get; set; }
            public string[] AvailableVariants { get; set; }

            public override string ToString() => $"{ProductName},{InStock},{Price}{(AvailableVariants?.Length > 0 ? "," + string.Join(",", AvailableVariants) : "")}";

            public static Product Parse(string csvRow)
            {
                var fields = csvRow.Split(',');

                return new Product
                {
                    ProductName = fields[0],
                    InStock = Convert.ToInt32(fields[1]),
                    Price= Convert.ToDouble(fields[2]),
                    AvailableVariants = fields.Skip(3).ToArray()
                };
            }
        }

        static void Main()
        {
            var prod1 = new Product
            {
                ProductName = "test1",
                InStock= 2,
                Price = 3,
                AvailableVariants = new string[]{ "variant1", "variant2" }
            };

            var filepath = @"C:\temp\test.csv";
            File.WriteAllText(filepath, prod1.ToString());

            var parsedRow = File.ReadAllText(filepath);
            var parsedProduct = Product.Parse(parsedRow);
            Console.WriteLine(parsedProduct);

            var noVariants = new Product
            {
                ProductName = "noVariants",
                InStock = 10,
                Price = 10
            };

            var prod3 = new Product
            {
                ProductName = "test2",
                InStock= 5,
                Price = 5,
                AvailableVariants = new string[] { "variant3", "variant4" }
            };

            var filepath2 = @"C:\temp\test2.csv";
            var productList = new List<Product> { parsedProduct, prod3, noVariants };
            File.WriteAllText(filepath2, string.Join("\r\n", productList.Select(x => x.ToString())));

            var csvRows = File.ReadAllText(filepath2);

            var newProductList = new List<Product>();
            foreach (var csvRow in csvRows.Split(new string[] { "\r\n" }, StringSplitOptions.None))
            {
                newProductList.Add(Product.Parse(csvRow));
            }
            newProductList.ForEach(Console.WriteLine);

            Console.ReadKey();
        }
    }
}

This code will work with a class that has a single object array property. Do you need something that can handle an object with multiple array properties?

wentimo
  • 471
  • 3
  • 12
  • So, basically it just puts variants in columns, that's handy. Unfortunately I'm not yet sure if I won't have more array fields in the model class. I'm still figuring out the details. – Reynevan Jun 20 '17 at 06:42
  • If you're going to have multiple arary fields you'll need to make them statically sized, you can only have one dynamically sized array which will be the last thing output (just like a param string[] property in a method call) – wentimo Jun 20 '17 at 07:00
-1

I have written some kind of library to write csv files, have a look:

public static class CsvSerializer
{
  public static bool Serialize<T>(string path, IList<T> data, string delimiter = ";")
  {
    var csvBuilder = new StringBuilder();
    var dataType = typeof(T);
    var properties = dataType.GetProperties()
                             .Where(prop => prop.GetCustomAttribute(typeof(CsvSerialize)) == null);

    //write header
    foreach (var property in properties)
    {
      csvBuilder.Append(property.Name);
      if (property != properties.Last())
      {
        csvBuilder.Append(delimiter);
      }
    }
    csvBuilder.Append("\n");
   //data
   foreach (var dataElement in data)
   {
     foreach (var property in properties)
     {
       csvBuilder.Append(property.GetValue(dataElement));
       if (property != properties.Last())
       {
         csvBuilder.Append(delimiter);
       }
     }
     csvBuilder.Append("\n");
   }

   File.WriteAllText(path, csvBuilder.ToString());

   return true;
 }
}

public class CsvSerialize : Attribute
{
}

Lets pretend you want to serialize following class:

public class MyDataClass
{
  [CsvSerialize]
  public string Item1 {get; set;}
  [CsvSerialize]
  public string Item2 {get; set;}
}

Then just do:

public void SerializeData(IList<MyDataClass> data)
{
  CsvSerializer.Serialize("C:\\test.csv", data);
}

It takes a IList of your class and writes a csv. It cant serialize arrays but that would be easy to implement.