反序列化 JSON 并添加回带有主记录的 DataTable

问题描述 投票:0回答:1

我有一个

DataTable
并且它有一些 JSON 数据,我想反序列化 JSON,并将其添加到主记录中。 JSON 列可以没有,也可以有多个。

如果该列有 JSON 数据,我将提取它并将其添加为列。运行良好。

dt = (DataTable)JsonConvert.DeserializeObject(jsonType2Column, (typeof(DataTable)));
for (int i = 0; i < dt.Columns.Count; i++)
{
    dtable.Columns.Add(dt.Columns[i].ColumnName, typeof(string));
}

我正在努力解决如何将数据添加到表中,其中 JSON 记录没有。行数不相同。

当我只有一个 JSON 列时,此代码工作正常。

for (int i = 0; i < dtJson2.Rows.Count; i++)
{
    for (int k = 0; k < dtJson2.Columns.Count; k++)
    {
        try
        {
            string ColumnName = dtJson2.Columns[k].ColumnName.ToString();
            dtrow[ColumnName] = dtJson2.Rows[i][ColumnName].ToString();                                       
        }
        catch (Exception ex)
        {
            continue;
        }
    }
    dtable.Rows.Add(dtrow);
}
c# json datatable json.net json-deserialization
1个回答
0
投票

我的解决方案可能不是一个很好的解决方案,但应该能够为您提供处理 JSON 行并将其提取到相应 DataTable 列的指导。

从你的问题来看,我担心具有相同名称的 JSON 属性可能出现在不同的列中。

DataTable
列名称不应冗余,否则可能会导致值被覆盖等行为。在这种情况下,您应该为该列命名,例如:“_”。

跳过从 JSON 数组中提取属性名称并将其添加到您已完成的

DataTable
列中的部分。

  1. 迭代每个数据行和列并提取 JSON。另外,重命名每个属性名称以注明它来自哪个(原始)列。

  2. 根据每个JSON数组的最大行数确定插入的最大行数。

  3. 逐行组合不同列中的每个 JSON 对象,并将其作为

    DataRow
    添加到
    DataTable
    中。

using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static DataTable AddJsonRowsToDataTable(DataTable dt, string[] jsonColumns, string[] toRemoveColumns)
{
    string jsonColumnNamePrefix = "{0}_{1}";
    DataTable resultDt = dt.Clone();

    foreach (string toRemoveColumn in toRemoveColumns)
        resultDt.Columns.Remove(toRemoveColumn);

    if (dt.Rows.Count == 0)
        return dt;

    // Add column for columns in JSON row
    foreach (string jsonColumn in jsonColumns)
    {
        if (dt.Columns.IndexOf(jsonColumn) == -1)
            continue;

        string jsonTypeColumn = dt.Rows[0][jsonColumn].ToString();
        if (String.IsNullOrEmpty(jsonTypeColumn))
            continue;

        DataTable jsonColDt = (DataTable)JsonConvert.DeserializeObject(jsonTypeColumn, (typeof(DataTable)));
        for (int i = 0; i < jsonColDt.Columns.Count; i++)
        {
            resultDt.Columns.Add(String.Format(jsonColumnNamePrefix, jsonColumn, jsonColDt.Columns[i].ColumnName), typeof(string));
        }
    }

    DataColumnCollection dataCols = dt.Columns;
    foreach (DataRow row in dt.Rows)
    {
        DataRow newRow = resultDt.NewRow();

        List<List<JObject>> jsonArrays = new List<List<JObject>>();
        foreach (DataColumn col in dataCols)
        {
            if (jsonColumns.Contains(col.ColumnName))
            {
                List<JObject> jObjects = new List<JObject>();

                string jsonTypeColumn = row[col].ToString();                    
                JArray jArray = JArray.Parse(jsonTypeColumn);

                // Extract JSON array, rename each property with prefix to know it is from which (original column)
                foreach (JObject jObj in jArray)
                {
                    JObject newJObj = new JObject();

                    foreach (var kvp in jObj)
                    {
                        newJObj.Add(String.Format(jsonColumnNamePrefix, col.ColumnName, kvp.Key), kvp.Value.ToString());
                    }

                    jObjects.Add(newJObj);
                }

                jsonArrays.Add(jObjects);
            }
            else
            {
                newRow[col.ColumnName] = row[col];
            }
        }

        int maxJsonRowsToAdd = jsonArrays.Select(x => x.Count).Max();
        if (maxJsonRowsToAdd > 0)
        {
            // Add number of rows based on max number of rows from JSON column
            for (int i = 0; i < maxJsonRowsToAdd; i++)
            {
                // Merge multiple JObjects from multiple JSON array by row
                JObject jObject = new JObject();
                foreach (var jsonArray in jsonArrays)
                {
                    if (jsonArray.ElementAtOrDefault(i) != null)
                    {
                        jObject.Merge(jsonArray.ElementAtOrDefault(i));
                    }
                }

                // Insert new data row for each merged JObject 
                DataRow jsonDtRow = resultDt.NewRow();
                jsonDtRow.ItemArray = newRow.ItemArray;
                foreach (var kvp in jObject)
                {
                    jsonDtRow[kvp.Key] = kvp.Value.ToString();
                }

                resultDt.Rows.Add(jsonDtRow);
            }
        }
        else
        {
            // Add default row if no rows in JSON column(s)
            resultDt.Rows.Add(newRow);
        }
    }

    return resultDt;
}

来电者:

string[] jsonColumnNames = new string[] { "Col3", "Col4" };
string[] toRemoveColumnNames = new string[] { "Col3", "Col4" };
DataTable resultDt = AddJsonRowsToDataTable(inputDt, jsonColumnNames, toRemoveColumnNames); 

© www.soinside.com 2019 - 2024. All rights reserved.