使用NewtonSoft序列化含空数据表的DataSet时丢失列信息,需保留列结构
这个问题我之前踩过坑!Newtonsoft.Json默认处理空DataTable的时候确实会只输出空数组[],完全丢掉列结构,特别影响后续需要依赖列信息的场景。
为什么会出现这个问题?
Newtonsoft.Json序列化DataTable的逻辑是遍历每一行数据,提取列名和对应值,如果表里没有任何行,就没有可遍历的内容,自然只会输出空数组,不会主动保留列元数据。
两种实用解决方案
方案1:给空表添加一行空行(最简单)
如果业务上允许空表存在一个“空行”,这是最快的解决办法——给每个空的DataTable添加一行由NewRow()生成的空行,这样序列化时就能提取到所有列名:
DataSet ds_v; // 假设此处已完成DataSet的填充操作 // 遍历所有表,处理空表 foreach (DataTable dt in ds_v.Tables) { if (dt.Rows.Count == 0) { dt.Rows.Add(dt.NewRow()); // 添加空行,保留列结构 } } // 正常序列化 string json = JsonConvert.SerializeObject(ds_v); System.IO.File.WriteAllText(Server.MapPath("~") + "/txt.json", json);
序列化后空表的输出会变成:
{ "Table": [ {"Column1": null, "Column2": null, "Column3": null} ] }
这样就能清晰看到所有列名了。
方案2:自定义Json转换器(更灵活,不修改原DataTable)
如果不想修改原DataSet的结构,可以写一个自定义的JsonConverter,强制序列化空表时输出包含列名的空对象:
public class DataTableJsonConverter : JsonConverter { public override bool CanConvert(Type objectType) { return typeof(DataTable).IsAssignableFrom(objectType); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var dt = value as DataTable; writer.WriteStartArray(); if (dt.Rows.Count == 0) { // 空表时,生成包含所有列的空对象 writer.WriteStartObject(); foreach (DataColumn col in dt.Columns) { writer.WritePropertyName(col.ColumnName); writer.WriteNull(); } writer.WriteEndObject(); } else { // 有数据时正常序列化每一行 foreach (DataRow row in dt.Rows) { writer.WriteStartObject(); foreach (DataColumn col in dt.Columns) { writer.WritePropertyName(col.ColumnName); serializer.Serialize(writer, row[col]); } writer.WriteEndObject(); } } writer.WriteEndArray(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 不需要反序列化的话可以直接抛出异常 throw new NotImplementedException("反序列化功能未实现"); } public override bool CanRead => false; }
然后序列化时指定这个转换器:
DataSet ds_v; // 填充DataSet... string json = JsonConvert.SerializeObject(ds_v, new DataTableJsonConverter()); System.IO.File.WriteAllText(Server.MapPath("~") + "/txt.json", json);
这个方案的好处是完全不修改原DataSet,只是在序列化层面做处理,适合对原数据完整性有要求的场景。
内容的提问来源于stack exchange,提问作者Unnikrishnan.S
相关产品推荐
相关产品推荐

