Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过ChoETL将C#中的嵌套JSON转换为CSV_C#_Json_Csv_Choetl - Fatal编程技术网

通过ChoETL将C#中的嵌套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

有人知道如何通过CHOETL(一个.NET的ETL框架)将下面嵌套的JSON转换为CSV吗?谢谢大家!

我正在使用此代码,但它只会返回第一个设备记录

代码:

                 {
                     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())