[英]Deserialization and Exporting of Nested JSON API Data to CSV
我需要從嵌套的 JSON 中的 API 中獲取一些數據並將其導出到 CSV。 在不創建多個類的情況下,我找不到將數據導出到 CSV 的正確語法(有數百個屬性,並且可以動態添加新屬性)。
來自 API 的 JSON 響應結構如下:
{
"data": [
{
"id": "1",
"type": "Bus",
"attributes": {
"property-two": "2020-12-10",
"property-three": "D",
"property-four": null,
"property-five": 5
}
},
{
"id": "2",
"type": "Car",
"attributes": {
"property-two": "2020-12-10",
"property-three": "D",
"property-four": null,
"property-five": 5
}
}
]
}
我們只需要將“屬性”節點從每個數據集中導出到 CSV,但似乎無法展平數據或僅提取這些節點。
以下代碼獲取JToken
對象的列表,但我不確定如何將其導出到 CSV 而無需再次重新序列化和反序列化。 數據類型是動態的,因為可以從中添加和刪除列。
var jsonObject = JObject.Parse(apiResponseString);
var items = jsonObject["data"].Children()["attributes"].ToList();
//TODO: Export to CSV, DataTable etc
是否可以僅反序列化來自屬性節點的數據,以及如何完成(無論是在初始JObject.Parse
上還是再次序列化JToken
列表)? 我沒有綁定到JObject
,所以也可以使用 Newtonsoft 或其他。
Using Json.Net's LINQ-to-JSON API (JObjects), you can convert your JSON data to CSV as shown below.
首先定義幾個簡短的擴展方法:
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
public static class JsonHelper
{
public static string ToCsv(this IEnumerable<JObject> items, bool includeHeaders = true)
{
if (!items.Any()) return string.Empty;
var rows = new List<string>();
if (includeHeaders)
{
rows.Add(items.First().Properties().Select(p => p.Name).ToCsv());
}
rows.AddRange(items.Select(jo =>
jo.Properties().Select(p => p.Value.Type == JTokenType.Null ? null : p.Value).ToCsv()
));
return string.Join(Environment.NewLine, rows);
}
public static string ToCsv(this IEnumerable<object> values)
{
const string quote = "\"";
const string doubleQuote = "\"\"";
return string.Join(",", values.Select(v =>
v != null ? string.Concat(quote, v.ToString().Replace(quote, doubleQuote), quote) : string.Empty
));
}
}
然后你可以這樣做:
var obj = JObject.Parse(json);
var csv = obj.SelectTokens("..attributes").Cast<JObject>().ToCsv();
這是一個工作演示: https://dotnetfiddle.net/NF2G2l
我最終在我的 Json Helper class 中創建了一個擴展方法,以將 JToken 枚舉轉換為數據表。 這滿足了簡單地導出到 CSV 的原始要求(我們使用具有將 DatatTable 轉換為 CSV 的方法的 Aspose Cells),而且還允許我們將數據表作為 object 使用而無需定義列。 最終結果如下所示:
工人 Class :
var stringResponse = await apiResponse.Content.ReadAsStringAsync();
var jsonObject = JObject.Parse(stringResponse);
var dataRows = jsonObject.SelectTokens("$..attributes").ToList();
var outputData = new DataTable("MyDataTable");
dataRows.AddToDataTable(outputData, pageNumber);
//TODO: Do something with outputData (to file, to object, to DB etc)
JsonHelper Class 新擴展方法
public static void AddToDataTable(this List<JToken> jTokens, DataTable dt, int pageNumber)
{
foreach (var token in jTokens)
{
JObject item;
JToken jtoken;
if (pageNumber == 1 && dt.Rows.Count == 0)
{
item = (JObject)token;
jtoken = item.First;
while (jtoken != null)
{
dt.Columns.Add(new DataColumn(((JProperty)jtoken).Name));
jtoken = jtoken.Next;
}
}
item = (JObject)token;
jtoken = item.First;
var dr = dt.NewRow();
while (jtoken != null)
{
dr[((JProperty)jtoken).Name] = ((JProperty)jtoken).Value.ToString();
jtoken = jtoken.Next;
}
dt.Rows.Add(dr);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.