通过ChoETL将C#中的嵌套JSON转换为CSV
有人知道如何通过CHOETL(一个.NET的ETL框架)将下面嵌套的JSON转换为CSV吗?谢谢大家! 我正在使用此代码,但它只会返回第一个设备记录 代码:通过ChoETL将C#中的嵌套JSON转换为CSV,c#,json,csv,choetl,C#,Json,Csv,Choetl,有人知道如何通过CHOETL(一个.NET的ETL框架)将下面嵌套的JSON转换为CSV吗?谢谢大家! 我正在使用此代码,但它只会返回第一个设备记录 代码: { using (var json = new ChoJSONReader("./test.json")) { csv.Write(json.Cast&l
{
using (var json = new ChoJSONReader("./test.json"))
{
csv.Write(json.Cast<dynamic>().Select(i => new
{
EquipmentId = i.GpsLocation.Equipment[0].EquipmentId,
InquiryValue = i.GpsLocation.Equipment[0].InquiryValue,
Timestamp = i.GpsLocation.Equipment[0].Timestamp
}));
}
}
"GpsLocation": {
"Equipment": [
{
"EquipmentId": "EQ00001",
"InquiryValue": [
"IV00001"
],
"Timestamp": "2020-01-01 01:01:01.01",
},
{
"EquipmentId": "EQ00002",
"InquiryValue": [
"IV00002"
],
"Timestamp": "2020-01-01 01:01:01.01"
}
]
}
}````
您的代码是合理的,但问题是您只使用i.GpsLocation.Equipment[0]编写数组中的第一个变量。相反,尝试通过将[0]放入for循环来循环所有内容,并将[0]更改为所述循环中的迭代变量。正如其他人所建议的,问题是您只查看数组的第一个元素 似乎控制序列化到CSV的内容的最简单方法是从JSON正确定义源对象。很方便 我在这里做的是查询所有JSON以返回一个
设备对象数组,而不管它们在层次结构中的什么位置(这意味着您可能需要根据完整的JSON对其进行更好的过滤)。
然后,基于JSON路径定义每个字段非常容易,只需将结果传递给CSVWriter
还可以查看我在各自的注释行中列出的一些问题
void Main()
{
var jsonString=“{\'GpsLocation\”:{\'EquipmentId\”:[{\'EQ00001\”,“InquiryValue\”:[\'IV00001\”],“Timestamp\”:“2020-01-01 01 01:01:01.01\”,{\'EquipmentId\”:“EQ00002\”,“InquiryValue\”:[\'IV00002\”,“Timestamp\”,“Timestamp\”:“2020-01-01:01:01.01\”;
var jsonReader=newstringreader(jsonString);
var csvWriter=new StringWriter();//输出到字符串,如果需要文件输出,请注释掉
//var csvWriter=newstreamwriter(“.\\your\u output.csv”);//写入您选择的文件
使用(var csv=新的ChocsWriter(csvWriter))
使用(var json=new ChoJSONReader(jsonReader)
.WithJSONPath(“$…设备[*]”,true)//首先将读取器的作用域设置为所有设备对象。请注意第二个参数。显然,您需要在此处传递true,否则它将不会返回任何内容
.WithField(“EquipmentId”,jsonPath:“$.EquipmentId”,isArray:false)//然后将数组中的每个字段的范围限定为所需的范围。由于需要标量值,因此传递`isArray:false`以提高可预测性
.WithField(“InquiryValue”,jsonPath:$.InquiryValue[0]”,isArray:false)//由于InquiryValue实际上是一个数组,因此您希望在此处获取第一个元素。如果不这样做,字段名称和值将倾斜
.WithField(“Timestamp”,jsonPath:“$.Timestamp”,fieldType:typeof(DateTime),isArray:false))//您还可以提供字段类型,否则它似乎默认为`string'`
{
csv.WithFirstLineHeader().Write(json);
}
Console.WriteLine(csvWriter.GetStringBuilder().ToString());//如果写入文件,请将其注释掉-您不需要它
}
更新摘要:
{
using (var json = new ChoJSONReader("./test.json"))
{
csv.Write(json.Cast<dynamic>().Select(i => new
{
EquipmentId = i.GpsLocation.Equipment[0].EquipmentId,
InquiryValue = i.GpsLocation.Equipment[0].InquiryValue,
Timestamp = i.GpsLocation.Equipment[0].Timestamp
}));
}
}
"GpsLocation": {
"Equipment": [
{
"EquipmentId": "EQ00001",
"InquiryValue": [
"IV00001"
],
"Timestamp": "2020-01-01 01:01:01.01",
},
{
"EquipmentId": "EQ00002",
"InquiryValue": [
"IV00002"
],
"Timestamp": "2020-01-01 01:01:01.01"
}
]
}
}````
Pivoted更新代码以依赖JSON路径范围-这似乎允许以相当低的工作量进行字段名操作
查看您的评论,您可能会稍微简化文件编写器-使用StreamWriter
而不是StringWriter
-例如,请参阅更新的代码
下面是从JSON生成CSV的工作示例
string json = @"{
""GpsLocation"": {
""Equipment"": [
{
""EquipmentId"": ""EQ00001"",
""InquiryValue"": [
""IV00001""
],
""Timestamp"": ""2020-02-01 01:01:01.01"",
},
{
""EquipmentId"": ""EQ00002"",
""InquiryValue"": [
""IV00002""
],
""Timestamp"": ""2020-01-01 01:01:01.01""
}
]
}
}";
StringBuilder csv = new StringBuilder();
using (var r = ChoJSONReader.LoadText(json)
.WithJSONPath("$.GpsLocation.Equipment")
.WithField("EquipmentId")
.WithField("InquiryValue", jsonPath: "InquiryValue[0]", fieldType: typeof(string))
.WithField("Timestamp", fieldType: typeof(DateTime))
)
{
using (var w = new ChoCSVWriter(csv)
.WithFirstLineHeader())
w.Write(r);
}
Console.WriteLine(csv.ToString());
输出:
EquipmentId,InquiryValue,Timestamp
EQ00001,IV00001,2/1/2020 1:01:01 AM
EQ00002,IV00002,1/1/2020 1:01:01 AM
您只使用i.GpsLocation.Equipment[0]执行某些操作,这确实是第一个设备记录。我怀疑你想翻阅所有的唱片。太棒了!非常感谢你。但还有一件事,代码工作得很好,但它不包括每列的标题(EquipmentId、InquiryValue、Timestamp)。我正在使用下面的代码将输出保存到CSV文件<代码>字符串csvOutput=(csvWriter.GetStringBuilder().ToString());File.writealText(“./foo.csv”,csvOutput.ToString())代码>