【问题标题】:C# Convert Json to CSVC# 将 Json 转换为 CSV
【发布时间】:2018-05-14 04:37:06
【问题描述】:

我有一个格式如下的 json 文件:

{
"HDRDTL":["SRNO","STK_IDN","CERTIMG"],
"PKTDTL":[
{"SRNO":"2814","STK_IDN":"1001101259","CERTIMG":"6262941723"},
{"SRNO":"2815","STK_IDN":"1001101269","CERTIMG":"6262941726"},
{"SRNO":"2816","STK_IDN":"1001101279","CERTIMG":"6262941729"}
],
"IMGTTL":
["CERTIMG","ARRIMG"],
"IMGDTL":{"CERTIMG":"CRd6z2uq3gvx7kk","ARRIMG":"ASd6z2uq3gvx7kk"}
}

“PKTDTL”数组是我需要转换为 csv 的部分。 如何在 C# 中实现这一点?

注意,例如,我在“PKTDTL”中只有3个项目,真正的json文件有数千行({“SRNO” ...})并且很大。

我编写了以下不起作用的代码。请参阅代码中注释的错误消息。

问题

  • 有人知道为什么失败吗?
  • 你有更好/替代的方法

    public static void ConvertJsonToCSV(string InFile)
    {
    
    string OutFile=InFile.Replace("json","csv");
    
    StreamReader sInFile = new StreamReader(InFile);
    StreamWriter sOutFile = new StreamWriter(OutFile);
    
    using (sInFile)
    {
        string sJson = sInFile.ReadToEnd();
    
        //*************************************************************
        // the below line failed, error message: unexpected json token
        // when reading datatable, expected startArray, got StartObject.
        //**************************************************************
    
        DataTable dt = JsonConvert.DeserializeObject<DataTable>(sJson);
        //DataTable dt = JsonConvert.DeserializeAnonymousType(sJson, new { Makes = default(DataTable) }).Makes;
    
        var sb = new StringBuilder();
    
        string[] columnNames = (from dc in dt.Columns.Cast<DataColumn>()
                                select dc.ColumnName).ToArray();
    
        sb.AppendLine(string.Join(",", columnNames));
    
        foreach (DataRow dr in dt.Rows)
        {
            foreach (object field in dr.ItemArray)
            {
                sb.Append(field.ToString().Replace(",", "") + ",");
            }
            sb.Replace(",", "\n", sb.Length - 1, 1);
        }
    
        sOutFile.Write(sb.ToString());
    
        sOutFile.Close();
        sInFile.Close();
    }
    

    }

【问题讨论】:

  • 判断您是否提出问题的一个重要线索是您是否使用 ? .这看起来你只需要使用调试器。
  • 你说不行。它有什么作用?
  • Keith:我知道错误在哪里。它位于“DataTable dt = JsonConvert.DeserializeObject(sJson);”这一行它说:读取 DataTable 时出现意外的 Json 令牌。预期 StartArray,得到 StartObject...
  • 你确定 JSON 是正确的吗?因为这里说不正确:jsonformatter.curiousconcept.com
  • Federico 是对的,前两个} 后面少了两个逗号,虽然这里可能只是复制粘贴错误。

标签: c# json csv choetl


【解决方案1】:

使用Cinchoo ETL - 一个开源库,您只需几行代码即可轻松完成转换

string json = @"{
    ""HDRDTL"":[""SRNO"",""STK_IDN"",""CERTIMG""],
    ""PKTDTL"":[
    {""SRNO"":""2814"",""STK_IDN"":""1001101259"",""CERTIMG"":""6262941723""},
    {""SRNO"":""2815"",""STK_IDN"":""1001101269"",""CERTIMG"":""6262941726""},
    {""SRNO"":""2816"",""STK_IDN"":""1001101279"",""CERTIMG"":""6262941729""}
    ],
    ""IMGTTL"":
    [""CERTIMG"",""ARRIMG""],
    ""IMGDTL"":{""CERTIMG"":""CRd6z2uq3gvx7kk"",""ARRIMG"":""ASd6z2uq3gvx7kk""}
    }";

StringBuilder sb = new StringBuilder();
using (var p = ChoJSONReader.LoadText(json).WithJSONPath("$..PKTDTL")
    )
{
    using (var w = new ChoCSVWriter(sb)
        .WithFirstLineHeader()
        )
        w.Write(p);
}

Console.WriteLine(sb.ToString());

输出:

SRNO,STK_IDN,CERTIMG
2814,1001101259,6262941723
2815,1001101269,6262941726
2816,1001101279,6262941729

查看 CodeProject 文章以获得更多帮助。

免责声明:我是这个库的作者。

【讨论】:

  • 图书馆工作得很好。问题:后跟两个点的 $ 是什么意思:“$..PKTDTL”。你也有关于使用你的方法的语法的文档吗?
  • 是 JSON 路径。有关更多信息,请参阅此链接goessner.net/articles/JsonPath
  • 如果值包含特殊字符,例如DEP%,输出将它们替换为下划线,变为 DEP_。有办法解决吗?
  • 我无法重现它。您在项目中使用什么版本的库?请尝试最新的并告诉我。
【解决方案2】:

我发现自己处于类似情况。这就是我所做的。首先,我创建了一个 JObject(使用 Newtonsoft.Json.Linq)让我们考虑您的 json 在一个名为“strJSON”的字符串变量中。

 JObject jsonObj= JObject.parse(strJSON);
 JObject  PKTDL=jsonObj["PKTDTL"] as JObject;
 IList<string> keys = PKTDL.Properties().Select(p => p.Name).ToList(); // this gives column names
 StringBuilder sb=new StringBuilder();
 string headers="";
 foreach(string key in keys)
 {
   headers+=","+key;
 }  
 sb.AppendLine(headers.TrimStart(','));
 foreach(JObject j in jsonObj["PKTDTL"]) //if jobject doesnt work try "JToken j"
 {
    string values="";
    foreach(string key in keys)
    {
       values+=","+jsonObj["PKTDTL"][key];
    }
    sb.AppendLine(values.TrimStart(','));
 }

   File.WriteAllText(filePath, sb.ToString());

然后将 sb 保存为 csv

【讨论】:

  • 第 2 行出错,“JToken”不包含“Properties”的定义,并且最佳扩展方法重载“Extensions.Properties(IEnumerable)”需要类型的接收器。知道如何解决这个问题吗?
  • 已编辑。在使用属性之前将 jsonObj["PKTDTL"] 转换为 jobject
【解决方案3】:

duplicate 类似的问题(请参阅那里的 JsonToCsv(string, string) 方法)。如果您已经在使用NewtonSoft Json.NETCsvHelper,您可以在ExpandoObject 的帮助下进行类似的转换。

    var jsonText = @"{
        ""HDRDTL"":[""SRNO"",""STK_IDN"",""CERTIMG""],
        ""PKTDTL"":[
        {""SRNO"":""2814"",""STK_IDN"":""1001101259"",""CERTIMG"":""6262941723""},
        {""SRNO"":""2815"",""STK_IDN"":""1001101269"",""CERTIMG"":""6262941726""},
        {""SRNO"":""2816"",""STK_IDN"":""1001101279"",""CERTIMG"":""6262941729""}
        ],
        ""IMGTTL"":
        [""CERTIMG"",""ARRIMG""],
        ""IMGDTL"":{""CERTIMG"":""CRd6z2uq3gvx7kk"",""ARRIMG"":""ASd6z2uq3gvx7kk""}
        }";

    var jtoken = JObject.Parse(jsonText).SelectToken("$..PKTDTL");
    var expandos = jtoken.ToObject<ExpandoObject[]>();
    string csvText;

    using (var writer = new StringWriter())
    {
        using (var csv = new CsvWriter(writer))
        {
            csv.WriteRecords(expandos as IEnumerable<dynamic>);
        }

        csvText = writer.ToString();
    }

    Console.WriteLine(csvText);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-27
    • 1970-01-01
    • 2015-08-23
    • 2019-08-21
    • 2011-04-27
    相关资源
    最近更新 更多