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

使用JsonConvert.SerializeObject序列化空行DataTable时保留列信息

解决Newtonsoft.Json序列化空DataTable丢失列信息的问题

默认情况下,Newtonsoft.Json序列化无数据行的DataTable时,只会输出空数组,丢失列定义信息。要保留列结构,可以通过自定义Json转换器实现,以下是具体方案:

实现自定义DataTable转换器

创建继承自JsonConverter<DataTable>的转换器,在序列化时主动输出列的元数据和行数据:

public class DataTableWithColumnsConverter : JsonConverter<DataTable>
{
    public override void WriteJson(JsonWriter writer, DataTable value, JsonSerializer serializer)
    {
        writer.WriteStartObject();

        // 序列化列信息
        writer.WritePropertyName("Columns");
        writer.WriteStartArray();
        foreach (DataColumn col in value.Columns)
        {
            writer.WriteStartObject();
            writer.WritePropertyName("ColumnName");
            writer.WriteValue(col.ColumnName);
            writer.WritePropertyName("DataType");
            writer.WriteValue(col.DataType.FullName);
            // 可按需添加其他列属性,比如AllowDBNull、DefaultValue等
            writer.WriteEndObject();
        }
        writer.WriteEndArray();

        // 序列化行数据
        writer.WritePropertyName("Rows");
        writer.WriteStartArray();
        foreach (DataRow row in value.Rows)
        {
            writer.WriteStartObject();
            foreach (DataColumn col in value.Columns)
            {
                writer.WritePropertyName(col.ColumnName);
                serializer.Serialize(writer, row[col]);
            }
            writer.WriteEndObject();
        }
        writer.WriteEndArray();

        writer.WriteEndObject();
    }

    public override DataTable ReadJson(JsonReader reader, Type objectType, DataTable existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 若需反序列化,可在此实现对应逻辑,本文重点为序列化,暂略
        throw new NotImplementedException("反序列化逻辑需自行实现");
    }
}

修改序列化代码

在调用JsonConvert.SerializeObject时,将自定义转换器传入JsonSerializerSettings:

DataTable dt = new DataTable();

DataColumn col1 = new DataColumn();
col1.DataType = typeof(Int32);
col1.ColumnName = "Id";
dt.Columns.Add(col1);

DataColumn col2 = new DataColumn();
col2.DataType = typeof(String);
col2.ColumnName = "Name";
dt.Columns.Add(col2);

DataSet ds = new DataSet();
ds.Tables.Add(dt);

var settings = new JsonSerializerSettings
{
    Formatting = Formatting.Indented,
    Converters = new List<JsonConverter> { new DataTableWithColumnsConverter() }
};

Console.WriteLine(JsonConvert.SerializeObject(ds, settings));

输出效果

此时序列化后的JSON会保留列信息和空行数组:

{
  "Table1": {
    "Columns": [
      {
        "ColumnName": "Id",
        "DataType": "System.Int32"
      },
      {
        "ColumnName": "Name",
        "DataType": "System.String"
      }
    ],
    "Rows": []
  }
}

补充说明

  • 如果不需要单独的Columns和Rows结构,也可以调整转换器逻辑,让空表输出一行包含列默认值的空行(比如Id为0,Name为null),但这种方式不如显式输出列结构清晰。
  • 若需要支持反序列化,需完善ReadJson方法,根据列信息重建DataTable并填充行数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 16:42:46