我有一个
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);
}
我的解决方案可能不是一个很好的解决方案,但应该能够为您提供处理 JSON 行并将其提取到相应 DataTable 列的指导。
从你的问题来看,我担心具有相同名称的 JSON 属性可能出现在不同的列中。
DataTable
列名称不应冗余,否则可能会导致值被覆盖等行为。在这种情况下,您应该为该列命名,例如:“_”。
跳过从 JSON 数组中提取属性名称并将其添加到您已完成的
DataTable
列中的部分。
迭代每个数据行和列并提取 JSON。另外,重命名每个属性名称以注明它来自哪个(原始)列。
根据每个JSON数组的最大行数确定插入的最大行数。
逐行组合不同列中的每个 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);