簡體   English   中英

嵌套 JSON API 數據的反序列化和導出到 CSV

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM