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

Newtonsoft Json.NET序列化DataSet时如何忽略默认值与空值?

问题:DataSet序列化JSON时无法排除值类型默认值(0、false)

维护旧代码库时必须使用DataSet做序列化操作,希望精简生成的JSON,移除空值以及int类型的0、bool类型的false。但现有代码并未排除第0行的IntValue(值为0)和第1行的BoolValue(值为false),求解决办法。

var dataSet = new DataSet();
dataSet.Tables.Add("MyTable");
dataSet.Tables[0].Columns.Add("StringValue", typeof(string));
dataSet.Tables[0].Columns.Add("IntValue", typeof(int));
dataSet.Tables[0].Columns.Add("BoolValue", typeof(bool));

var row = dataSet.Tables[0].NewRow();
row["StringValue"] = "Hello";
row["IntValue"] = 0;
row["BoolValue"] = true;
dataSet.Tables[0].Rows.Add(row);

row = dataSet.Tables[0].NewRow();
row["StringValue"] = null;
row["IntValue"] = 123;
row["BoolValue"] = false;
dataSet.Tables[0].Rows.Add(row);

var settings = new JsonSerializerSettings()
{
    NullValueHandling = NullValueHandling.Ignore,
    DefaultValueHandling = DefaultValueHandling.Ignore,
    Formatting = Formatting.Indented
};

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

/*输出结果:

{
  "MyTable": [
    {
      "StringValue": "Hello",
      "IntValue": 0,
      "BoolValue": true
    },
    {
      "IntValue": 123,
      "BoolValue": false
    }
  ]
}

*/

解决办法

Json.NET对DataSet/DataRow的默认序列化逻辑里,不会把明确设置的0、false这类值类型默认值判定为"默认值"——因为DataSet中的字段是强类型的,这些值被视为有效赋值,而非未初始化的默认状态,所以DefaultValueHandling.Ignore不会生效。下面提供两种可行方案:

方案一:自定义JsonConverter处理DataRow

写一个自定义转换器,在序列化DataRow时逐个检查字段值,若为对应类型的默认值则跳过序列化:

public class DataRowDefaultValueConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(DataRow).IsAssignableFrom(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var row = (DataRow)value;
        writer.WriteStartObject();

        foreach (DataColumn column in row.Table.Columns)
        {
            var columnValue = row[column];
            // 跳过DBNull和值类型默认值
            if (columnValue == DBNull.Value)
                continue;
            
            var type = column.DataType;
            if (type.IsValueType)
            {
                var defaultValue = Activator.CreateInstance(type);
                if (EqualityComparer<object>.Default.Equals(columnValue, defaultValue))
                    continue;
            }
            
            writer.WritePropertyName(column.ColumnName);
            serializer.Serialize(writer, columnValue);
        }

        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // 若不需要反序列化,直接抛出异常或返回null
        throw new NotImplementedException("DataRowDefaultValueConverter不支持反序列化");
    }
}

然后在序列化设置中添加这个转换器:

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

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

方案二:序列化前预处理DataRow

遍历所有DataRow,将值为默认值的字段设为DBNull.Value,这样NullValueHandling.Ignore就会忽略它们:

// 预处理DataSet中的所有行
foreach (DataTable table in dataSet.Tables)
{
    foreach (DataRow row in table.Rows)
    {
        foreach (DataColumn column in table.Columns)
        {
            var value = row[column];
            if (value == DBNull.Value)
                continue;
            
            var type = column.DataType;
            if (type.IsValueType)
            {
                var defaultValue = Activator.CreateInstance(type);
                if (EqualityComparer<object>.Default.Equals(value, defaultValue))
                {
                    row[column] = DBNull.Value;
                }
            }
        }
    }
}

// 再用原设置序列化
var settings = new JsonSerializerSettings()
{
    NullValueHandling = NullValueHandling.Ignore,
    Formatting = Formatting.Indented
};

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

两种方案都能得到预期的精简JSON:

{
  "MyTable": [
    {
      "StringValue": "Hello",
      "BoolValue": true
    },
    {
      "IntValue": 123
    }
  ]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 09:47:20