【问题标题】:Converting objects with string[] properties to CSV or Excel将具有 string[] 属性的对象转换为 CSV 或 Excel
【发布时间】:2017-06-20 05:01:50
【问题描述】:

是否有任何库可以将具有数组属性的对象序列化为 .csv?

假设我有这个模型:

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

这样的事情可以做吗?

编辑:我需要以 csv/excel 格式呈现一些数据。问题是,我不确定是否有一种简单的方法可以使用 CSV 序列化库实现我想要的,或者我是否应该专注于编写 Excel 原生文件。

我正在寻找的结果示例:

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

最有效的方法是什么?

【问题讨论】:

标签: c# .net csv serialization .net-4.5


【解决方案1】:

我不知道有任何库会这样做,这是一个控制台示例,说明我如何从 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();
        }
    }
}

此代码适用于具有单个对象数组属性的类。您是否需要可以处理具有多个数组属性的对象的东西?

【讨论】:

  • 所以,基本上它只是将变体放在列中,这很方便。不幸的是,我还不确定模型类中是否不会有更多的数组字段。我还在弄清楚细节。
  • 如果您要拥有多个数组字段,您需要使它们静态调整大小,您只能有一个动态调整大小的数组,这将是最后输出的内容(就像参数字符串 [ ] 方法调用中的属性)
【解决方案2】:

我写了一些库来写csv文件,看看:

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
{
}

假设你想序列化以下类:

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

那就这样吧:

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

它需要你类的 IList 并写入一个 csv。 它不能序列化数组,但这很容易实现。

【讨论】:

    猜你喜欢
    • 2021-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 2018-03-27
    • 2011-04-27
    • 1970-01-01
    相关资源
    最近更新 更多