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

如何在序列化时排除无序列化字段/属性的对象?

序列化时排除空默认对象的实用方案

嘿,这个场景我太熟悉了——预填充的JObject反序列化后留下一堆空默认对象,序列化出来完全没用还占空间。下面给你几个靠谱的解决办法,都是基于.NET生态里最常用的Json序列化工具(Json.NET/Newtonsoft.Json),你可以根据自己的场景选:

1. 自定义ContractResolver,全局过滤空对象

这是最灵活的方式,能全局生效,不用每次序列化都手动处理。

首先写个辅助方法判断对象是不是“空”(所有属性/字段都是默认值):

private static bool IsObjectEmpty(object obj)
{
    if (obj == null) return true;
    var type = obj.GetType();
    
    // 检查所有公共属性
    foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        var defaultValue = prop.PropertyType.IsValueType ? Activator.CreateInstance(prop.PropertyType) : null;
        var currentValue = prop.GetValue(obj);
        if (!Equals(currentValue, defaultValue))
        {
            return false;
        }
    }
    
    // 如果有公共字段也一起检查(根据你的Item类调整)
    foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance))
    {
        var defaultValue = field.FieldType.IsValueType ? Activator.CreateInstance(field.FieldType) : null;
        var currentValue = field.GetValue(obj);
        if (!Equals(currentValue, defaultValue))
        {
            return false;
        }
    }
    return true;
}

然后自定义一个ContractResolver,在处理数组的时候自动跳过空对象:

public class SkipEmptyObjectsResolver : DefaultContractResolver
{
    protected override JsonArrayContract CreateArrayContract(Type objectType)
    {
        var contract = base.CreateArrayContract(objectType);
        // 包装原有的序列化逻辑,添加过滤
        var originalWriter = contract.ItemConverter.WriteJson;
        contract.ItemConverter.WriteJson = (writer, value, serializer) =>
        {
            if (!IsObjectEmpty(value))
            {
                originalWriter(writer, value, serializer);
            }
        };
        return contract;
    }
}

使用的时候只要把这个Resolver加到序列化设置里就行:

var settings = new JsonSerializerSettings
{
    ContractResolver = new SkipEmptyObjectsResolver(),
    Formatting = Formatting.Indented
};
var json = JsonConvert.SerializeObject(yourItemArray, settings);

2. 写专门的JsonConverter处理Item数组

如果不想全局生效,只想针对Item数组处理,可以写个专属的Converter:

public class ItemArrayConverter : JsonConverter<Item[]>
{
    public override void WriteJson(JsonWriter writer, Item[] value, JsonSerializer serializer)
    {
        writer.WriteStartArray();
        foreach (var item in value)
        {
            if (!IsObjectEmpty(item)) // 复用上面的IsObjectEmpty方法
            {
                serializer.Serialize(writer, item);
            }
        }
        writer.WriteEndArray();
    }

    public override Item[] ReadJson(JsonReader reader, Type objectType, Item[] existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 反序列化保持默认逻辑就行,毕竟你是覆盖预填充的JObject
        return serializer.Deserialize<List<Item>>(reader).ToArray();
    }
}

用的时候把Converter加到序列化设置里:

var settings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new ItemArrayConverter() },
    Formatting = Formatting.Indented
};
var json = JsonConvert.SerializeObject(yourItemArray, settings);

3. 序列化前手动过滤(最简单粗暴的办法)

如果你的场景不复杂,不想写一堆扩展代码,最直接的就是序列化前先把空对象删掉:

var filteredItems = yourItemArray.Where(item => !IsObjectEmpty(item)).ToArray();
var json = JsonConvert.SerializeObject(filteredItems, Formatting.Indented);

这个办法胜在直观,容易维护,就是每次序列化都要手动处理一遍。

额外说明

如果你用的是.NET Core 3.0+内置的System.Text.Json,思路是完全一样的:要么写自定义JsonConverter,要么序列化前过滤。只是API细节略有不同,比如判断属性默认值的逻辑、Converter的写法稍微调整下就行。

另外,你可以根据自己的业务需求修改IsObjectEmpty的逻辑——比如某些属性即使是默认值,但你觉得不算“空”,就可以在方法里把这些属性排除掉。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:17:23