gpt4 book ai didi

c# - 使用 ServiceStack.Text 将动态对象列表序列化为 CSV

转载 作者:太空宇宙 更新时间:2023-11-03 23:45:25 27 4
gpt4 key购买 nike

我所有的 EF 类(class)都有一个 Projection()帮助我选择我想从类中投影到 SQL 查询的方法:

例子:

    public static Expression<Func<Something, dynamic>> Projection()
{
return e => new
{
something = e.SomethingId,
name = e.Name,
requiredThingId = e.RequiredThingId,
requiredThing = new
{
requiredThingId = e.RequiredThing.RequiredThingId,
name = e.RequiredThing.Name,
...
},
optionalThingId = e.OptionalThingId,
optionalThing = e.OptionalThingId == null ? null : new
{
optionalThingId = e.OptionalThing.OptionalThingId,
name = e.OptionalThing.Name
}
...
};
}

我像这样使用这些投影方法:<​​/p>

  List<dynamic> projected = dbContext.Something.Select(Something.Projection()).ToList();

通过这种方式,我可以在我的项目中重复使用我的投影。

我想使用 ServiceStack.Text 将这些列表序列化为 CSV。

我这样做:

 string csvString = CsvSerializer.SerializeToCsv<dynamic>(Something.Select(Something.Projection()).ToList());

byte[] csvBytes = System.Text.Encoding.Unicode.GetBytes(csvString);

return File(csvBytes, "text/csv", "foo.csv");

但结果是一个空的 csv(csvString 充满了“\r\n”,仅此而已)

问题:

  • 我是否正确使用了 SerializeToCsv()方法?
  • 我可以使用<dynamic>吗?在这个图书馆?
  • 实现我的目标的建议?

对于上面的示例,所需的 CSV 会展平所有属性,例如:

  "somethingId";"name";"requiredThingId";"requiredThing.requiredThingId";"requiredThing.name";"optionalThingId";"optionalThing.optionalThingId";"optionalThing.name"

最佳答案

我会回答我自己的问题,但不会标记为已接受,希望有新的更好的答案..

Am I using correctly the SerializeToCsv() method? Can I use dynamic in this library?

回答:两者都可以,但需要 ServiceStack.Text v4.0.36(可在 MyGet 获得,而非 Nuget)

Suggestions for achieving my purpose?

答案:用ServiceStack.Text可以序列化为 CSV a List<dynamic> ,但所有嵌套属性都将呈现为 JSON,并且它们不会被展平,例如:

   List<dynamic> list = new List<dynamic>();
list.Add(new
{
name = "john",
pet = new
{
name = "doggy"
}
});

string csv = CsvSerializer.SerializeToCsv(list);

此列表将序列化为此 csv:

name, pet
"john", { name = "doggy" }

而不是这个 csv,正如我所期待的那样:

name, pet_name
"john", "doggy"

所以...我终于写了这段代码:

public class CsvHelper
{
public static string GetCSVString(List<dynamic> inputList)
{
var outputList = new List<Dictionary<string, object>>();

foreach (var item in inputList)
{
Dictionary<string, object> outputItem = new Dictionary<string, object>();
flatten(item, outputItem, "");

outputList.Add(outputItem);
}

List<string> headers = outputList.SelectMany(t => t.Keys).Distinct().ToList();

string csvString = ";" + string.Join(";", headers.ToArray()) + "\r\n";

foreach (var item in outputList)
{
foreach (string header in headers)
{
if (item.ContainsKey(header) && item[header] != null)
csvString = csvString + ";" + item[header].ToString();
else
csvString = csvString + ";";
}

csvString = csvString + "\r\n";
}

return csvString;
}

private static void flatten(dynamic item, Dictionary<string, object> outputItem, string prefix)
{
if (item == null)
return;

foreach (PropertyInfo propertyInfo in item.GetType().GetProperties())
{
if (!propertyInfo.PropertyType.Name.Contains("AnonymousType"))
outputItem.Add(prefix + "__" + propertyInfo.Name, propertyInfo.GetValue(item));
else
flatten(propertyInfo.GetValue(item), outputItem, (prefix.Equals("") ? propertyInfo.Name : prefix + "__" + propertyInfo.Name));
}
}
}

它的作用是:

  1. 它扁平化列表,使列表中对象的所有属性都是原始属性(例如:没有嵌套属性)

  2. 它从该扁平化列表创建一个 CSV。

这个算法是O(n*m),是
n: 列表中的项目数
m:每个项目内的属性数(包括嵌套属性)

关于c# - 使用 ServiceStack.Text 将动态对象列表序列化为 CSV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27734201/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com