You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何反序列化JSON并合并行数不一致的数据至DataTable主记录

解决DataTable中多行JSON数据与主记录的合并问题

核心问题在于主表行与JSON反序列化后的数据行需要明确关联逻辑:当JSON是数组(多行)时,主表的一行需要扩展为多行,每行对应JSON数组中的一条记录;当JSON是单个对象(单行)时,直接合并到主表当前行。以下是支持多JSON列、自动处理行数不一致的实现方案:

实现步骤与代码

1. 核心合并方法

封装通用方法,负责将单行主记录与某列的JSON反序列化数据合并:

using Newtonsoft.Json;
using System.Data;

public static List<DataRow> MergeJsonToRow(DataRow mainRow, string jsonColumnName, string jsonColumnPrefix = "")
{
    var resultRows = new List<DataRow>();
    string jsonData = mainRow[jsonColumnName]?.ToString();
    if (string.IsNullOrWhiteSpace(jsonData))
    {
        // JSON为空,返回原行副本
        var emptyRow = mainRow.Table.NewRow();
        mainRow.ItemArray.CopyTo(emptyRow.ItemArray, 0);
        resultRows.Add(emptyRow);
        return resultRows;
    }

    // 反序列化JSON为DataTable
    DataTable jsonDt = JsonConvert.DeserializeObject<DataTable>(jsonData);
    if (jsonDt == null || jsonDt.Rows.Count == 0)
    {
        var emptyRow = mainRow.Table.NewRow();
        mainRow.ItemArray.CopyTo(emptyRow.ItemArray, 0);
        resultRows.Add(emptyRow);
        return resultRows;
    }

    // 为JSON列添加前缀,避免列名冲突
    foreach (DataColumn col in jsonDt.Columns)
    {
        col.ColumnName = string.IsNullOrEmpty(jsonColumnPrefix) ? col.ColumnName : $"{jsonColumnPrefix}_{col.ColumnName}";
    }

    // 遍历JSON行,合并到主行副本中
    foreach (DataRow jsonRow in jsonDt.Rows)
    {
        var newRow = mainRow.Table.NewRow();
        // 复制主行原有数据
        mainRow.ItemArray.CopyTo(newRow.ItemArray, 0);
        // 合并JSON行数据
        foreach (DataColumn col in jsonDt.Columns)
        {
            if (!newRow.Table.Columns.Contains(col.ColumnName))
            {
                newRow.Table.Columns.Add(col.ColumnName, col.DataType);
            }
            newRow[col.ColumnName] = jsonRow[col] ?? DBNull.Value;
        }
        resultRows.Add(newRow);
    }

    return resultRows;
}

2. 处理多JSON列的完整流程

遍历主表每一行,依次处理所有JSON列,逐步合并数据:

public static DataTable MergeAllJsonColumns(DataTable mainTable, List<string> jsonColumnNames)
{
    if (jsonColumnNames == null || !jsonColumnNames.Any())
    {
        return mainTable.Copy(); // 无JSON列,直接返回原表副本
    }

    // 创建结果表结构(复制主表结构)
    DataTable resultTable = mainTable.Clone();

    // 预添加所有JSON列的字段,避免重复添加
    foreach (string jsonColName in jsonColumnNames)
    {
        string sampleJson = mainTable.AsEnumerable()
                                     .FirstOrDefault(r => !string.IsNullOrWhiteSpace(r[jsonColName]?.ToString()))?[jsonColName]?.ToString();
        if (!string.IsNullOrWhiteSpace(sampleJson))
        {
            DataTable tempDt = JsonConvert.DeserializeObject<DataTable>(sampleJson);
            if (tempDt != null)
            {
                foreach (DataColumn col in tempDt.Columns)
                {
                    string newColName = $"{jsonColName}_{col.ColumnName}";
                    if (!resultTable.Columns.Contains(newColName))
                    {
                        resultTable.Columns.Add(newColName, col.DataType);
                    }
                }
            }
        }
    }

    // 遍历主表行,逐个处理JSON列
    foreach (DataRow mainRow in mainTable.Rows)
    {
        List<DataRow> currentRows = new List<DataRow> { mainRow };

        foreach (string jsonColName in jsonColumnNames)
        {
            List<DataRow> tempRows = new List<DataRow>();
            foreach (DataRow row in currentRows)
            {
                tempRows.AddRange(MergeJsonToRow(row, jsonColName, jsonColName));
            }
            currentRows = tempRows;
        }

        // 将合并后的行导入结果表
        foreach (DataRow mergedRow in currentRows)
        {
            resultTable.ImportRow(mergedRow);
        }
    }

    return resultTable;
}

3. 使用示例

假设主表dtable包含Id、InfoJson、DetailJson两个JSON列,调用方式如下:

// 定义所有含JSON的列名
var jsonColumns = new List<string> { "InfoJson", "DetailJson" };
// 执行合并
DataTable mergedTable = MergeAllJsonColumns(dtable, jsonColumns);

关键说明

  • 列名冲突处理:通过给JSON列添加原列名前缀(如InfoJson_Name),避免不同JSON列的同名字段冲突。
  • 空JSON处理:若JSON为空或反序列化后无数据,保留原主行数据。
  • 行数适配:自动处理JSON是单个对象(单行)或数组(多行)的情况,主行会根据JSON行数自动扩展或直接合并。

内容的提问来源于stack exchange,提问作者SU_Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 00:00:34