使用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
相关产品推荐
相关产品推荐

