【问题标题】:C# CsvHelper - Records with different number of propertiesC# CsvHelper - 具有不同数量属性的记录
【发布时间】:2022-08-19 00:53:10
【问题描述】:

我在遗留项目上使用 CsvHelper(版本 7.1.0 ,如果可能的话,我宁愿现在保留该版本)

我有一个要保存为 csv 的具有不同数量属性的对象列表。

例如:

var list = new List<dynamic>(){
  {id=1, image1=\"xxx\", state=\"ok\"},
  {id=2, image1=\"xxx\", image2=yyy, state=\"ok\"}
  {id=3, image1=\"xxx\", state=\"ok\"}
}

编辑澄清:我作为公开发布的 API 的一部分接收对象 客户可以决定发送给我

{
  {id=1, image1=\"xxx\", state=\"ok\"},
  {id=2, image1=\"xxx\", image2=\"yyy\", state=\"ok\"}
  {id=3, image1=\"xxx\", state=\"ok\"}
}

而另一个可以发送

{
  {id=1, MyImage1=\"xxx\", state=\"ok\"},
  {id=2, MyImage1=\"xxx\", MyImage2=\"yyy\", state=\"ok\"}
  {id=3, MyImage1=\"xxx\", MyComment=\"please discard\", state=\"ok\"}
}

这就是为什么我(至少我认为)需要使用某种动态或 expandoObject

最简单的情况是所有记录都具有相同的属性,但我遇到了特定边缘情况的问题


当我写:

var csv = new CsvWriter(writer);
csv.WriteRecords(list);

标头基于列表中的第一项,因此在我的情况下,由于缺少某些标头,csv 会变得混乱,我会得到类似的结果:

id image1 state
1 xxx ok
2 xxx yyy ok
3 xxx ok

我想要的是以下内容:

id image1 image2 state
1 xxx ok
2 xxx yyy ok
3 xxx ok

我需要保持标题的顺序和列表的排序。

到目前为止,我最好的解决方案是识别具有最高属性计数的项目,并将具有空值的缺失属性添加到所有其他项目......

有没有更聪明的方法来实现我的需要?

谢谢!

  • 不要使用dynamic。在类中创建 Dictionary&lt;string, object&gt; 并用于序列化为 csv 格式,string - 属性名称,object - 值。
  • 但对象是动态的。我可以得到一个图像或一千个图像。有解决方法吗?
  • 为什么使用dynamic
  • @AtActionPark,使用列表-如果您有一张图像,则列表中将有 1 个元素,如果为 1k,则列表中将有 1k 个元素。
  • 将 \"images\" 保存为字符串:url1,url2,url3

标签: c# csvhelper


【解决方案1】:

我可以让它工作的唯一方法是浏览所有记录并找到所有潜在的标题。然后遍历每个记录的标题列表,以查看记录是否包含标题。如果是,写出值,如果不是,写一个空字段。

void Main()
{
    var records = new List<dynamic>(){
      new {id=1, image1="xxx", state="ok"},
      new {id=2, image1="xxx", image2="yyy", state="ok"},
      new {id=3, image1="xxx", state="ok"}
    };
    
    var headers = new List<string>();
    
    foreach (var record in records)
    {
        var properties = record.GetType().GetProperties();
        var previousItem = string.Empty;
        
        foreach (var property in properties)
        {
            var previousItemIndex = headers.FindIndex(a => a.Contains(previousItem));           
            var currentItemIndex = headers.FindIndex(a => a.Contains(property.Name));
            
            if (currentItemIndex == -1)
            {
                headers.Insert(previousItemIndex + 1, property.Name);
            }
            
            previousItem = property.Name;
        }
    }
    
    using (var csv = new CsvWriter(Console.Out, CultureInfo.InvariantCulture))
    {
        foreach (var header in headers)
        {
            csv.WriteField(header);
        }
        
        csv.NextRecord();
        
        foreach (var record in records)
        {
            foreach (var header in headers)
            {
                var property = record.GetType().GetProperty(header);
                
                if (property != null)
                {
                    csv.WriteField(property.GetValue(record, null));
                }
                else
                {
                    csv.WriteField(string.Empty);
                }
            }
            csv.NextRecord();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    • 2014-01-27
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多