【发布时间】:2019-07-16 19:39:24
【问题描述】:
我有 json 对象的列表。每个 json 对象都具有公共属性和该 json 对象独有的一些属性。喜欢下面的示例
{"FirstName":"foo","LastName":"bar"}
{"FirstName":"jhon","LastName":"dow"}
{"FirstName":"james","LastName":"smith","Age":26}
{"LastName":"jones","Age":30, "Address":"1234 Test Drive"}
我想使用 CsvHelper 创建 CSV 报告,其中每个属性都是标题。当属性不存在时,该列的值应该为空
这是我目前的实现,当然没有考虑额外的属性
var records = new List<dynamic>();
foreach (var jObj in result)
{
var record = new ExpandoObject();
foreach (var property in jObj)
{
record.TryAdd(property.Key, property.Value.ToString());
}
records.Add(record);
}
using (var writer = new StreamWriter(filePath))
{
using (var csv = new CsvWriter(writer))
{
csv.WriteRecords(records);
}
}
所以在上面的例子中,生成的 csv 应该有 4 个标题
FirstName,LastName,Age 和 Address
请注意,记录数可能以千为单位
更新 1
以下是我的临时解决方案,直到我找到更好的方法来做到这一点而无需循环两次
[Fact]
public async Task CreateCSVFromJObjects()
{
// arrange
var list = new JObject[]
{
JObject.FromObject(new { FirstName = "foo",LastName = "bar" }),
JObject.FromObject(new { FirstName = "john",LastName = "doe" }),
JObject.FromObject(new { FirstName = "james",LastName = "smith", Age = 26 }),
JObject.FromObject(new { LastName = "bar", Address = "123 Test Drive" })
}.ToList();
//act
var headers = new HashSet<string>();
foreach (var j in list)
{
foreach (var p in j)
{
if (!headers.Contains(p.Key))
{
headers.Add(p.Key);
}
}
}
using (var writer = new StreamWriter("C:\\temp\\test.csv"))
{
using (var csv = new CsvWriter(writer))
{
foreach (var header in headers)
{
csv.WriteField(header);
}
await csv.NextRecordAsync();
foreach (var jObj in list)
{
foreach (var header in headers)
{
var token = jObj[header];
if (token != null)
{
csv.WriteField(token.ToString());
}
else
{
csv.WriteField("");
}
}
await csv.NextRecordAsync();
}
}
}
}
【问题讨论】:
-
你知道所有可能的标题吗?
-
未知.. 除非我先循环所有 JObjects。这将导致循环两次
-
你能将 json 反序列化为 JObject 以外的类型吗?编写对象集合是可行的,因为属性名称成为标题。
-
对象未知。我们收集了我转换为 JObjects 的 json 字符串。每个 JObject 中的属性数量不会超过 10 个,但 JObject 的数量可能以数千为单位
-
@LP13 显示的示例是否准确地提供数据?
标签: c# .net .net-core csvhelper