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

使用C#向DataTable插入数据时丢失最后一列的问题

问题描述

从前端通过JavaScript获取到一段JSON字符串,插入DataTable时最后一列(incident列)无法成功插入,现有代码仅能正确处理前4列。

获取到的JSON字符串:

[{"CompanayID":"k123","Role":"Admin","Country":"UK","Asset":"HD"}, {"CompanayID":"k234","Role":"User","Country":"US","Asset":"HD12","incident":"abc 1"}]

使用的C#代码:

DataTable dt = new DataTable("UserDetails");
JavaScriptSerializer serializer = new JavaScriptSerializer();
object[] objCustomers = (object[])serializer.DeserializeObject(customers);
var columnNames = ((Dictionary<string, object>)objCustomers[0]).Select(x => x.Key).ToList();
for (int i = 0; i < columnNames.Count; i++)
{
    dt.Columns.Add(columnNames[i]);
}
for (int i = 0; i < objCustomers.Length; i++)
{
    Dictionary<string, object> keyValue = (Dictionary<string, object>)objCustomers[i];
    DataRow dr = dt.NewRow();
    foreach (KeyValuePair<string, object> item in keyValue)
    {
        for (int k = 0; k < columnNames.Count(); k++)
        {
            if (item.Key == columnNames[k].ToString())
            {
                dr[columnNames[k]] = item.Value;
                break;
            }
        }
    }
    dt.Rows.Add(dr);
}
问题原因

代码仅提取第一个JSON对象的所有键作为DataTable的列名,但第一个对象没有incident字段,导致DataTable从未创建该列。处理第二个JSON对象时,即使存在incident键,也找不到对应的列来插入值。

解决方案

方案1:动态收集所有字段(适合结构不固定的JSON)

遍历所有序列化后的对象,收集所有出现过的键并去重,再基于这些键创建DataTable列,确保不会遗漏任何字段。

修改后的代码:

DataTable dt = new DataTable("UserDetails");
JavaScriptSerializer serializer = new JavaScriptSerializer();
object[] objCustomers = (object[])serializer.DeserializeObject(customers);

// 收集所有对象的键,去重
var allColumnNames = new HashSet<string>();
foreach (var obj in objCustomers)
{
    var dict = (Dictionary<string, object>)obj;
    foreach (var key in dict.Keys)
    {
        allColumnNames.Add(key);
    }
}

// 创建所有列
foreach (var columnName in allColumnNames)
{
    dt.Columns.Add(columnName);
}

// 填充数据
foreach (var obj in objCustomers)
{
    var keyValue = (Dictionary<string, object>)obj;
    DataRow dr = dt.NewRow();
    foreach (var item in keyValue)
    {
        dr[item.Key] = item.Value;
    }
    // 对象没有的字段自动留空(DataRow默认值为DBNull)
    dt.Rows.Add(dr);
}

方案2:使用强类型对象(适合结构固定的JSON)

如果JSON字段结构相对固定,先定义对应类,反序列化成强类型列表后再转换为DataTable,类型更安全且代码更简洁。

首先定义实体类:

public class UserDetail
{
    public string CompanayID { get; set; }
    public string Role { get; set; }
    public string Country { get; set; }
    public string Asset { get; set; }
    public string incident { get; set; } // 可选字段,允许为null
}

转换代码:

JavaScriptSerializer serializer = new JavaScriptSerializer();
List<UserDetail> userList = serializer.Deserialize<List<UserDetail>>(customers);

DataTable dt = new DataTable("UserDetails");
// 基于类属性创建列
foreach (var prop in typeof(UserDetail).GetProperties())
{
    dt.Columns.Add(prop.Name, prop.PropertyType);
}

// 填充数据
foreach (var user in userList)
{
    DataRow dr = dt.NewRow();
    dr["CompanayID"] = user.CompanayID;
    dr["Role"] = user.Role;
    dr["Country"] = user.Country;
    dr["Asset"] = user.Asset;
    dr["incident"] = user.incident ?? DBNull.Value; // 处理null值
    dt.Rows.Add(dr);
}
补充说明
  • 方案1更灵活,适配JSON字段动态增减的场景;
  • 方案2更规范,适合字段结构稳定的场景,便于维护;
  • 注意原JSON中CompanayID存在拼写错误(正确应为CompanyID),可根据需求统一修正。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 04:55:21