JsonConvert.SerializeObject 从空数据表中删除列

JsonConvert.SerializeObject Removes Columns From Empty Datatable

提问人:LongNeckTimmy 提问时间:11/9/2023 更新时间:11/12/2023 访问量:53

问:

我正在使用JsonConvert.SerializeObject来序列化DataSets。有时,我的 DataSet 中的 DataTable 没有任何行,但 DataTable 确实有列。当我序列化 DataSet 时,如果 DataTable 没有任何行,则所有列都会从 DataTable 中删除。

我想知道是否有办法序列化 DataSet 并且不会丢失没有行的 DataTable 上的列。

这是一个示例来演示我的问题。在这里,我创建一个 DataTable 并向其添加两列。然后,我将 DataTable 添加到 DataSet 并序列化 DataSet:

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);

Console.WriteLine(JsonConvert.SerializeObject(ds, Formatting.Indented));

输出:

{
  "Table1": []
}

如您所见,一旦我序列化了 DataSet,所有列信息都会从我的 DataTable 中丢失。有谁知道解决这个问题的解决方法?

C# json.net

评论

1赞 dbc 11/9/2023
这是 Json.NET 的 DataTable 序列化的已知限制,请参阅 Serializing a DataSet with empty data tables lost all column information #1343
3赞 dbc 11/9/2023
您的选择似乎是 1) 使用 XML 而不是 JSON,因为 XML 保留了架构信息;2)按照使用空数据表序列化数据集中的建议添加一个空列,这将丢失所有列信息;3) 编写您自己的自定义转换器,例如如何在 JSON 中为空 DataTable 包含列元数据此 github 注释中的转换器。

答:

0赞 Serge 11/12/2023 #1

最简单的方法是添加一个空行

if (dt.Rows.Count==0) dt.Rows.Add();

Console.WriteLine(JsonConvert.SerializeObject(ds, Newtonsoft.Json.Formatting.Indented));

输出

{
  "Table1": [
    {
      "Id": null,
      "Name": null
    }
  ]
}

或者,如果您的 DS 有多个表

    foreach (DataTable t in ds.Tables)
        if (t.Rows.Count==0) t.Rows.Add();

如果你有很多这样的转换器,你可以编写一个自定义转换器

public class DsJsonConverter : JsonConverter<DataSet>
{
    public override DataSet ReadJson(JsonReader reader, Type objectType, DataSet existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        DataSet ds = JObject.Load(reader).ToObject<DataSet>();

        foreach (DataTable t in ds.Tables)
            if (t.Rows.Count == 1)
            {
                var isEmptyRow = true;
                for (int i = 0; i < t.Columns.Count; i++)
                {
                    if (!string.IsNullOrEmpty(t.Rows[0][i].ToString())) isEmptyRow = false;
                    break;
                }
                if (isEmptyRow) t.Rows.RemoveAt(0);
            }
        return ds;
    }

    public override void WriteJson(JsonWriter writer, DataSet value, JsonSerializer serializer)
    {
        foreach (DataTable t in value.Tables)
            if (t.Rows.Count == 0) t.Rows.Add();

        writer.WriteRaw(JsonConvert.SerializeObject(value));
    }
}

评论

0赞 Ann L. 11/12/2023
我不明白为什么这被否决了。投票。
0赞 Serge 11/12/2023
我很高兴。谢谢。