C# - 展平嵌套的 Json

Posted

技术标签:

【中文标题】C# - 展平嵌套的 Json【英文标题】:C# - Flatten Nested Json 【发布时间】:2021-09-05 02:37:03 【问题描述】:

我有多个具有不同布局的 JSON,我正在尝试创建一些代码来展平这些 JSON,然后将其转换为 Datatable。

示例 JSON 1


  "d": 
    "results": [
      
        "__metadata": 
          "uri": "myuri.com",
          "type": "String"
        ,
        "jobNumber": "123456789",
        "numberVacancy": "1",
        "some_obj": 
          "__metadata": 
            "uri": "myuri.com",
            "type": "String"
          ,
          "code": "000012356"
        ,
        "anothernested": 
          "results": [
            
              "__metadata": 
                "uri": "myuri.com",
                "type": "String"
              ,
              "picklistLabels": 
                "results": [
                  
                    "__metadata": 
                      "uri": "myuri.com",
                      "type": "String"
                    ,
                    "label": "Casual"
                  ,
                  
                    "__metadata": 
                      "uri": "myuri.com",
                      "type": "String"
                    ,
                    "label": "Casual"
                  
                ]
              
            
          ]
        
      ,
      
        "__metadata": 
          "uri": "myuri.com",
          "type": "String"
        ,
        "jobNumber": "987654321",
        "numberVacancy": "1",
        "some_obj": 
          "__metadata": 
            "uri": "myuri.com",
            "type": "String"
          ,
          "code": "000012356"
        ,
        "anothernested": 
          "results": [
            
              "__metadata": 
                "uri": "myuri.com",
                "type": "String"
              ,
              "picklistLabels": 
                "results": [
                  
                    "__metadata": 
                      "uri": "myuri.com",
                      "type": "String"
                    ,
                    "label": "Casual"
                  ,
                  
                    "__metadata": 
                      "uri": "myuri.com",
                      "type": "String"
                    ,
                    "label": "Casual"
                  
                ]
              
            
          ]
        
      
    ]
  

我希望如何将 JSON 扁平化为数据表的示例。

__metadata/uri __metadata/type jobNumber numberVacancy some_obj/__metadata/uri some_obj/__metadata/type some_obj/code anothernested/results/0/__metadata/uri anothernested/results/0/__metadata/type anothernested/results/0/picklistLabels/results/0/__metadata/uri anothernested/results/0/picklistLabels/results/0/__metadata/type anothernested/results/0/picklistLabels/results/0/label anothernested/results/0/picklistLabels/results/1/__metadata/uri anothernested/results/0/picklistLabels/results/1/__metadata/type anothernested/results/0/picklistLabels/results/1/label
myuri.com String 123456789 1 myuri.com String 12356 myuri.com String myuri.com String Casual myuri.com String Casual
myuri.com String 987654321 1 myuri.com String 12356 myuri.com String myuri.com String Casual myuri.com String Casual

我将从 d.results 索引中展平 JSON。

到目前为止,我有这个会将结果数组中的每个单独的 Json 展平为字符串字典。但是,我不确定如何将其转换为数据表,请记住,有时字典中的元素可能不是相同的顺序,或者每个 JSON 数组中的元素可能或多或少。

IEnumerable<JToken> jTokens = jsonObject.Descendants().Where(p => p.Count() == 0);
results1 = jTokens.Aggregate(new Dictionary<string, string>(), (properties, jToken) =>
                    
                        properties.Add(jToken.Path, jToken.ToString());
                        return properties;
                    );

【问题讨论】:

【参考方案1】:

您可以尝试Cinchoo ETL - 一个满足您需求的开源库。

using (var r = new ChoJSONReader("*** YOUR JSON FILE PATH ***")
    .WithJSONPath("$..d.results")
    .Configure(c => c.NestedColumnSeparator = '/')
    )

    var dt = r.AsDataTable();
    Console.WriteLine(dt.Dump());

输出:

__metadata/uri,__metadata/type,jobNumber,numberVacancy,some_obj/__metadata/uri,some_obj/__metadata/type,some_obj/code,anothernested/results/0/__metadata/uri,anothernested/results/0/__metadata/type,anothernested/results/0/picklistLabels/results/0/__metadata/uri,anothernested/results/0/picklistLabels/results/0/__metadata/type,anothernested/results/0/picklistLabels/results/0/label,anothernested/results/0/picklistLabels/results/1/__metadata/uri,anothernested/results/0/picklistLabels/results/1/__metadata/type,anothernested/results/0/picklistLabels/results/1/label
myuri.com,String,123456789,1,myuri.com,String,000012356,myuri.com,String,myuri.com,String,Casual,myuri.com,String,Casual
myuri.com,String,987654321,1,myuri.com,String,000012356,myuri.com,String,myuri.com,String,Casual,myuri.com,String,Casual

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

【讨论】:

【参考方案2】:

要从源 json 创建数据表,您需要以下代码:

JObject jsonObject = JObject.Parse(json);
List<string> jpaths = jsonObject.Descendants().OfType<JProperty>().Where(jp => jp.Value is JArray).Select(jp => jp.Path).ToList();
List<JToken> rowtokens = jsonObject.SelectTokens("$.d.results.[*]").ToList();

DataTable resultTable = new DataTable();
resultTable.Columns.AddRange(((JObject)rowtokens[0]).Descendants().OfType<JProperty>().Where(jp => jp.Value is JValue).Select(jp => new DataColumn(jp.Path)).ToArray());
foreach (JToken rowtoken in rowtokens)

    resultTable.Rows.Add(((JObject)rowtoken).Descendants().OfType<JProperty>().Where(jp => jp.Value is JValue).Select(jp => jp.Value.ToString()).ToArray());

            

【讨论】:

谢谢你,这很好用。展平整个 JSON 并将每个对象分开。

以上是关于C# - 展平嵌套的 Json的主要内容,如果未能解决你的问题,请参考以下文章

使用 jq 展平嵌套的 JSON

展平双嵌套 JSON

展平嵌套的 JSON 对象

使用 normalize 展平三重嵌套 JSON

如何展平多级/嵌套 JSON?

用嵌套列表和嵌套字典列表展平一个非常大的 Json